commit c2b447610cf7361c7dfb0609e3de5cff192600e7 Author: Martin Stickelbroeck Date: Sun Sep 27 20:00:36 2026 +0200 Baseline: Saumwacht 0.15.0 (Phase 20A) vor dem Umbau zu Champions of Luneraria 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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c727e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.godot/ +*.tmp +docs/screenshots/ +test-results/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..da6ef1a --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Saumwacht · Die grüne Kluft + +Ein Tower-Defense-Autobattler für Godot 4 mit **Glutpakt und Wurzelbund**, Rivalen-KI, 20-Wellen-Expedition und Acht-Wellen-Kurzpartie. Zwanzig spielbare Wächter, zehn Wellengegner, Arbeiter und Kernkristalle besitzen ausgearbeitete 3D-Modelle. + +## Start + +**Demo 0.15.0:** Im übergeordneten `dist` das passende [Windows-ZIP](../dist/Saumwacht-Windows-x64-0.15.0.zip) oder [Linux-ZIP](../dist/Saumwacht-Linux-x64-0.15.0.zip) vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh`. Godot und Blender werden zum Spielen nicht benötigt. Bei Vulkan-Problemen `Kompatibilitaet.bat` bzw. `Kompatibilitaet.sh` nutzen. + +[Aktueller Stand: Phase 20A · Hauptmenü und Bundauswahl](../docs/phase-20a-hauptmenue.md). 0.15.0 bringt einen neuen Spieleinstieg vor einer 3D-Bühne an der Grünen Kluft, eine Bundwahl über gestaltete Karten und ein gemeinsames Menü-Theme; erstmals sind auch [Funkenlanze](../docs/phase-18-funkenlanze.md) und [Glasballiste](../docs/phase-19-glasballiste.md) im Paket. [Frühere Integrationsschritte](../docs/phase-17-integration-und-demo.md). + +Aus dem Quellprojekt: `./play.sh`, `godot --path .` oder `project.godot` in Godot 4.7.2 öffnen und F5 drücken. + +**Neue Partie** öffnet die Bundwahl mit Partielänge; Rivalenbund, KI-Stufe und Bauzeit liegen unter *Weitere Einstellungen*. Nach **Partie beginnen** hilft **Startformation**: drei Wächter für 185 Gold beim Wurzelbund, 180 Gold beim Glutpakt. **Leertaste / Kampf starten** beginnt den Autokampf. Standardmäßig gibt es keinen Baudruck; auch die Abrechnung wartet auf dich. Das frühere Zeitlimit lässt sich im Menü zuschalten. + +Die [Landschaft](../docs/phase-10-grafik-und-landschaft.md), die [Beleuchtung und die Menüs](../docs/phase-13-grafik-und-menu.md) sind cineastisch überarbeitet: warmer Schlüssel, kühles Fülllicht, Glaspanels und ein neues Titelmenü. + +Die [Ringborke](../docs/phase-11-ringborke.md), der [Funkenleser](../docs/phase-12-arbeiter.md), die [Basaltbastion](../docs/phase-15-basaltbastion.md), das [Quellgeflecht](../docs/phase-16-quellgeflecht.md), die [Funkenlanze](../docs/phase-18-funkenlanze.md) und die [Glasballiste](../docs/phase-19-glasballiste.md) besitzen gewichtete Skelette. Der Arbeiter zeigt Werkzeugkontakt, Aufnehmen, Einfüllen und Rückkehr; **V → Funkenleser** öffnet den Betrachter. Die Basaltbastion nimmt zum Kampfbeginn ihre Schutzhaltung ein; empfangene Heilung zeigt einen Effektpuls, die eigene Fähigkeit ihre zugehörige Animation. Der Kristall reagiert auf Aktivierung und Schaden. Die [Engine-Prüfung](../docs/engine-pruefung-2026-09-19.md) bleibt die Grundlage für einen späteren Vergleich. + +## Bedienung + +| Eingabe | Aktion | +| --- | --- | +| 1–5 / Baukarte | Wächter und Modellvorschau wählen | +| Linksklick auf freies Feld | Einen Wächter kaufen, platzieren und auswählen | +| Shift + Linksklick | Mehrere Wächter platzieren | +| Linksklick auf Wächter | Aufwertung, Versetzen, Verkauf und Zielwahl öffnen | +| Rechtsklick / Esc | Bauauftrag oder Versetzen abbrechen | +| Rückgängig | Letzte erfolgreiche Bauaktion zurücknehmen | +| Leertaste | Kampf starten / nächste Bauphase | +| C / Basis ansehen | Arbeiter und Kristall ansehen / zur Front zurückkehren | +| Tab | Eigene Front / Rivalenfront | +| P / 1×–2× | Pause / Kampfgeschwindigkeit | +| Mausrad / Q–E | Zoom / Kamera drehen | +| Mittlere Maustaste ziehen / R | Kamera verschieben / zurücksetzen | +| F1 | Optionen, Steuerung, neue Partie und Beenden | +| V | Modelle groß ansehen und Bewegungen abspielen | +| M / F11 | Stumm / Vollbild | + +Gold kauft Wächter, Aufwertungen und Arbeiter. Jeder aktive Arbeiter liefert **zehn Funken pro Bauphase**; neue Arbeiter erst ab der folgenden Welle. Ab Welle 3 kannst du Funken für Söldner ausgeben: Sie greifen den Rivalen an und steigern dauerhaft dein Goldeinkommen. Die Anzeige nennt nur freie, noch nicht reservierte Funken. Gekaufte Wächter kehren nach dem Kampf vollständig geheilt in ihre Formation zurück. + +Der Wurzelbund nutzt Heilung, Ranken und Keimbrand. Seine Heiler müssen nahe an der Front stehen. Der Glutpakt kombiniert Schutz, Brand und Flächenschaden. Nach der letzten Welle gewinnt der Kristall mit mehr HP; ein zerstörter Kern beendet das Duell früher. + +## Umfang und Prüfung + +[Hauptmenü 20A](../docs/phase-20a-hauptmenue.md) · [Mindestpolygonregel](../docs/pruefung-mindestpolygonregel.md) · [Änderungen, Modelle und Balance](../docs/phase-10-grafik-und-landschaft.md) · [Grafik & Menü](../docs/phase-13-grafik-und-menu.md) · [Arbeiter](../docs/phase-12-arbeiter.md) · [Builds](docs/phase20-builds.md) · [QA](docs/QA.md) · [Spielansicht](docs/screenshots/phase20/after/ingame-build-1920x1080.png) · [Menü](docs/screenshots/phase20/after/title-1920x1080.png). + +```bash +godot --path . --resolution 1920x1080 res://tools/verify_menu.tscn +godot --path . --resolution 1920x1080 res://tools/menu_review.tscn +godot --headless --path . res://tests/test_runner.tscn +python3 tools/verify_arbeiter.py +godot --headless --path . res://tools/verify_arbeiter.tscn +godot --headless --path . res://tools/verify_ability_events.tscn +godot --path . res://tools/verify_material_sides.tscn +python3 tools/verify_glasballiste.py +godot --headless --path . res://tools/verify_glass.tscn +python3 tools/build_demo.py --check-only +godot --headless --path . res://tools/verify_phase5.tscn -- --phase9 +godot --headless --path . -- --faction-test +godot --path . -- --faction-test --ui-only +godot --headless --path . -- --expedition-test +godot --headless --path . -- --smoke-test +``` + +`--faction-test` prüft Fähigkeiten, Fraktionsbesitz, Wirtschaft, Bedienung und vier normale KI-Partien. Mit Grafikausgabe entstehen Screenshots unter `user://phase10-captures`. `--ui-only` lässt die vier vollständigen Partien weg. Die alten Prüfmodi setzen ausdrücklich Glutpakt und zeitgesteuerte Bauphasen, um die bisherigen Ergebnisse zu vergleichen. + +Die Grafik verwendet Forward+; der beiliegende OpenGL-Modus zeigt dieselbe Geometrie ohne SSAO und Glow. Ringborke, Funkenleser, Basaltbastion, Quellgeflecht, Funkenlanze und Glasballiste nutzen gewichtete Skelette; die anderen Figuren bewegen weiterhin starre Gelenkgruppen. Die Illustrationen sind Stilvorlagen für eigenständige 3D-Modelle. Balance ist anhand reproduzierbarer KI-Partien eingegrenzt; menschliche Spieltests sind weiterhin wichtig. Kein Speichern laufender Partien, kein Multiplayer. Windows ist exportiert; ein nativer Windows-Test steht aus. + +## Assetquellen + +Das Menü-Diorama entsteht aus [build_menu_stage.py](assets-source/phase20/build_menu_stage.py) (Blender) mit [GLB](assets/environment/menu-stage.glb) und `assets/menu_stage_manifest.json`; Embleme und Steuerungs-Icons liegen als SVG unter `assets/ui`, das Menü-Theme in `scripts/ui/theme`. + +Die Glasballiste entsteht vollständig aus ihrem [Generator](assets-source/phase19/build_glasballiste.py); daraus folgen [Blender-Szene](assets-source/phase19/glasballiste.blend), [GLB](assets/characters/glasballiste.glb) und Manifest. [Modellbericht](../docs/phase-19-glasballiste.md). + +Der Funkenleser liegt als [Blender-Szene](assets-source/phase12/arbeiter.blend) mit editierbaren Einzelteilen und Arbeitsclips vor. Der [GLB-Export](assets/characters/arbeiter.glb) enthält das gewichtete Modell. [Modellbericht](../docs/phase-12-arbeiter.md). + +Die Ringborke liegt als [Blender-Szene](assets-source/phase11/ringborke.blend) mit editierbaren Einzelteilen und Animationen vor. Der [GLB-Export](assets/characters/ringborke.glb) enthält das gewichtete Modell und seine Clips. [Modellbericht und Wiederaufbau](../docs/phase-11-ringborke.md). + +Die Kartenquelle liegt unter `assets-source/phase10/verdant-rift.blend`, der Spielexport unter `assets/environment`. 59 Figuren- und Bauwerk-GLBs liegen unter `assets/models`, bearbeitbare Blender-Szenen unter `assets-source/phase4/blend`. Glutpakt und Wurzelbund haben je zehn Modelle im höheren Detailgrad; Nietenkonvent und Nebelchor sind noch nicht spielbar. Die [Blender-Pipeline](assets-source/phase4/README.md) liefert außerdem neun eigenständige Skripte. [Direkte Referenzvergleiche](docs/screenshots/phase4/reference-gallery.html) und `godot --path . res://tools/model_gallery.tscn` öffnen die Modellwerkstatt. + +Die bisherigen Einstellungen bleiben im Benutzerordner `Saumwacht · Glutpakt` erhalten. Exportdateien enthalten nur Spieldaten und benötigte Manifeste; Quellen, Dokumentation und Entwicklungswerkzeuge werden nicht mit ausgeliefert. diff --git a/assets-source/.gdignore b/assets-source/.gdignore new file mode 100644 index 0000000..e69de29 diff --git a/assets-source/phase10/bake_bark.py b/assets-source/phase10/bake_bark.py new file mode 100644 index 0000000..0123b8c --- /dev/null +++ b/assets-source/phase10/bake_bark.py @@ -0,0 +1,61 @@ +"""Render authored, periodic 4D wood grain at native 4096px in Blender. +This is a procedural material bake, not an enlargement of a bitmap. +The torus coordinate mapping makes the material seamless on all four edges. +""" +import bpy, math, json +from pathlib import Path +PROJECT=Path(__file__).resolve().parents[2] +out=PROJECT/'assets/materials/phase10' +scene=bpy.data.scenes.new('Bark_PBR_4K');bpy.context.window.scene=scene +scene.render.engine='CYCLES';scene.cycles.samples=1 +scene.render.resolution_x=4096;scene.render.resolution_y=4096;scene.render.resolution_percentage=100 +scene.render.image_settings.file_format='PNG';scene.render.image_settings.color_mode='RGB';scene.render.image_settings.color_depth='8' +scene.render.image_settings.compression=90;scene.render.dither_intensity=0 +scene.view_settings.view_transform='Standard';scene.view_settings.look='None' +scene.render.film_transparent=False +bpy.ops.mesh.primitive_plane_add(size=2) +plane=bpy.context.object;plane.name='Bark_material_bake_surface' +mat=bpy.data.materials.new('SW_4K_Sculpted_Oak');mat.use_nodes=True;plane.data.materials.append(mat) +n=mat.node_tree.nodes;n.clear();links=mat.node_tree.links +def node(kind): return n.new(kind) +def mathnode(op,a,b=None): + obj=node('ShaderNodeMath');obj.operation=op + if isinstance(a,(float,int)): obj.inputs[0].default_value=a + else: links.new(a,obj.inputs[0]) + if b is not None: + if isinstance(b,(float,int)):obj.inputs[1].default_value=b + else:links.new(b,obj.inputs[1]) + return obj.outputs[0] +uv=node('ShaderNodeTexCoord');split=node('ShaderNodeSeparateXYZ');links.new(uv.outputs['UV'],split.inputs[0]) +u=mathnode('MULTIPLY',split.outputs['X'],math.tau) +v=mathnode('MULTIPLY',split.outputs['Y'],math.tau) +co=node('ShaderNodeCombineXYZ') +links.new(mathnode('MULTIPLY',mathnode('COSINE',u),10),co.inputs['X']) +links.new(mathnode('MULTIPLY',mathnode('SINE',u),10),co.inputs['Y']) +links.new(mathnode('MULTIPLY',mathnode('COSINE',v),.7),co.inputs['Z']) +grain=node('ShaderNodeTexNoise');grain.noise_dimensions='4D' +links.new(co.outputs[0],grain.inputs['Vector']);links.new(mathnode('MULTIPLY',mathnode('SINE',v),.7),grain.inputs['W']) +grain.inputs['Scale'].default_value=2.6;grain.inputs['Detail'].default_value=7;grain.inputs['Roughness'].default_value=.73 +height=node('ShaderNodeValToRGB') +height.color_ramp.elements[0].position=.27;height.color_ramp.elements[0].color=(.07,.07,.07,1) +height.color_ramp.elements[1].position=.67;height.color_ramp.elements[1].color=(.8,.8,.8,1) +height.color_ramp.elements.new(.43).color=(.14,.14,.14,1) +height.color_ramp.elements.new(.51).color=(.55,.55,.55,1) +links.new(grain.outputs['Fac'],height.inputs[0]) +emit=node('ShaderNodeEmission');output=node('ShaderNodeOutputMaterial');links.new(emit.outputs[0],output.inputs['Surface']) +links.new(height.outputs[0],emit.inputs['Color']) +bpy.ops.object.camera_add(location=(0,0,3));camera=bpy.context.object;camera.data.type='ORTHO';camera.data.ortho_scale=2;scene.camera=camera +scene.render.filepath=str(out/'oak-height-4k.png');bpy.ops.render.render(write_still=True) +colors=node('ShaderNodeValToRGB') +def linear(hexcolor): + rgb=[int(hexcolor[i:i+2],16)/255 for i in (0,2,4)] + return tuple(c/12.92 if c<=.04045 else ((c+.055)/1.055)**2.4 for c in rgb)+(1,) +colors.color_ramp.elements[0].position=.0;colors.color_ramp.elements[0].color=linear('302B23') +colors.color_ramp.elements[1].position=1;colors.color_ramp.elements[1].color=linear('B09A6D') +colors.color_ramp.elements.new(.18).color=linear('4B3C2A') +colors.color_ramp.elements.new(.51).color=linear('766041') +colors.color_ramp.elements.new(.74).color=linear('94855D') +links.new(height.outputs[0],colors.inputs[0]);links.new(colors.outputs[0],emit.inputs['Color']) +scene.render.filepath=str(out/'oak-albedo-4k.png');bpy.ops.render.render(write_still=True) +bpy.data.libraries.write(str(PROJECT/'assets-source/phase10/oak-material-4k.blend'),{scene},fake_user=True,compress=True) +print('PBR_BAKE_PASS: two native 4096 x 4096 8-bit runtime maps; original seamless procedural material.') diff --git a/assets-source/phase10/build_sanctuary.py b/assets-source/phase10/build_sanctuary.py new file mode 100644 index 0000000..c9c2c63 --- /dev/null +++ b/assets-source/phase10/build_sanctuary.py @@ -0,0 +1,274 @@ +"""Saumwacht: the Verdant Rift, an editable Blender environment in real metres. + +The two 6x8 gameplay grids remain unobstructed. All vegetation, bridges, +architectural details and rock strata are actual meshes, not a backdrop. +Run: ALSOFT_DRIVERS=null blender -b --python-exit-code 1 --python this_file.py +""" +from pathlib import Path +import sys, math, random, json, hashlib +import bpy +from mathutils import Vector, noise + +PROJECT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(PROJECT/'assets-source/phase4/blender')) +from common import mesh_object, ellipsoid, cylinder, cone, srgb_to_linear +from reference_high_detail import hd_box, hd_curve, hd_ring, hd_rod, hd_finish + +R = random.Random(10092026) +scene = bpy.data.scenes.new('The_Verdant_Rift') +bpy.context.window.scene = scene +scene.unit_settings.system = 'METRIC' +scene['description'] = 'Two intact 12 x 40 metre paths; forest sanctuary above a river gorge.' +M = {} +for key, color, rough, metal in [ + ('limestone','918875',.89,0),('cliff','666D68',.92,0), + ('soil','404F39',.97,0),('bark','534332',.93,0), + ('leaf_dark','314B38',.89,0),('leaf_mid','526A42',.85,0), + ('leaf_light','8B9655',.79,0),('brass','BEA36D',.53,.65), + ('teal','69CEB9',.36,.2),('coral','DF9A7A',.36,.2), + ('flower','C4BB93',.72,0),('paving','707367',.92,0)]: + mat=bpy.data.materials.new('ENV_'+key); mat.use_nodes=True + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + bs=mat.node_tree.nodes.get('Principled BSDF') + bs.inputs['Base Color'].default_value=(*c,1) + bs.inputs['Roughness'].default_value=rough + bs.inputs['Metallic'].default_value=metal + if key in ['teal','coral']: + bs.inputs['Emission Color'].default_value=(*c,1) + bs.inputs['Emission Strength'].default_value=.65 + M[key]=mat + +def p(x,z,h=0): return (x,-z,h) +def box(name,x,z,h,sx,sz,sh,key='limestone',radius=.035,angle=0): + return hd_box(name,p(x,z,h),(sx,sz,sh),M[key],radius,(0,0,angle)) + +def rock(name,x,z,h,sx,sz,sh,seed=0): + # Angular, eroded stratified rock, authored rings rather than round spheres. + rng=random.Random(seed+917);verts=[];faces=[];sides=14;levels=13 + phase=rng.uniform(0,6.28) + for row in range(levels): + t=row/(levels-1) + shoulder=.55+.45*math.sin(math.pi*t)**.3 + ledge=[1.0,.93,1.05,.96][row%4] + for col in range(sides): + angle=math.tau*col/sides+phase + n=noise.noise(Vector((math.cos(angle)*2,math.sin(angle)*2,t*3+seed))) + radius=shoulder*ledge*(1+n*.16) + px=math.cos(angle)*sx*radius + py=math.sin(angle)*sz*radius + pz=(t*2-1)*sh+n*.07*sh + verts.append((px,py,pz)) + for row in range(levels-1): + for col in range(sides): + a=row*sides+col;b=row*sides+(col+1)%sides + faces.append((a,b,b+sides,a+sides)) + faces.append(tuple(reversed(range(sides)))) + faces.append(tuple((levels-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,M['cliff']);obj.location=p(x,z,h) + hd_finish(obj,.035,2,False) + return obj + +def leaf_mesh(name,center,radius,seed): + """An airy spray of individually curved, closed six-sided leaves.""" + rng=random.Random(seed); verts=[]; faces=[] + for i in range(90): + direction=Vector((rng.uniform(-1,1),rng.uniform(-1,1),rng.uniform(-.6,.7))).normalized() + point=Vector(center)+direction*radius*rng.random()**.38 + tangent=Vector((rng.uniform(-1,1),rng.uniform(-1,1),rng.uniform(-.4,.4))).normalized() + side=tangent.cross(Vector((0,0,1))).normalized() + length=rng.uniform(.18,.35); width=length*.47; base=len(verts) + verts.extend([tuple(point-tangent*length),tuple(point-side*width),tuple(point+tangent*length), + tuple(point+side*width),tuple(point+Vector((0,0,length*.22))),tuple(point-Vector((0,0,.018)))]) + faces.extend([tuple(base+j for j in f) for f in [(0,1,4),(1,2,4),(2,3,4),(3,0,4),(1,0,5),(2,1,5),(3,2,5),(0,3,5)]]) + return mesh_object(name,verts,faces,M[['leaf_dark','leaf_mid','leaf_light'][seed%3]]) + +def tree(x,z,size,seed): + rng=random.Random(seed); base=Vector(p(x,z,-.3)) + lean=Vector((rng.uniform(-.5,.5),rng.uniform(-.5,.5),0))*size + height=size*3.8 + trunk=[base,base+Vector((0,0,height*.28)),base+lean*.7+Vector((0,0,height*.68)),base+lean+Vector((0,0,height))] + hd_curve('Tree_%d_Trunk'%seed,trunk,[size*.38,size*.25,size*.15,.035],M['bark'],18,9) + for j in range(7): + a=j*math.tau/7 + root=base+Vector((math.cos(a),math.sin(a),0))*size*1.3 + root.z=-.21 + hd_curve('Tree_%d_Root_%d'%(seed,j),[root,base+Vector((math.cos(a)*.3,math.sin(a)*.3,.3))*size,trunk[1]],[.03,size*.14,.12*size],M['bark'],10,6) + for j in range(11): + a=j*2.399+seed + branch=base+lean*.5+Vector((0,0,height*(.4+j*.035))) + length=size*(1.7-j*.065) + end=branch+Vector((math.cos(a)*length,math.sin(a)*length,size*(.9+j*.055))) + hd_curve('Tree_%d_Branch_%d'%(seed,j),[branch,(branch+end)*.5+Vector((0,0,.18)),end],[size*.11,size*.065,.012],M['bark'],10,6) + leaf_mesh('Tree_%d_Canopy_%d'%(seed,j),end,size*.68,seed*100+j) + leaf_mesh('Tree_%d_Spray_%d'%(seed,j),end*.55+branch*.45,size*.5,seed*200+j) + +def fern(x,z,scale,seed): + rng=random.Random(seed); verts=[]; faces=[] + base=Vector(p(x,z,-.08)) + for j in range(7): + a=math.tau*j/7+seed + direction=Vector((math.cos(a),math.sin(a),0)) + side=direction.cross(Vector((0,0,1))) + length=scale*rng.uniform(.65,1.05) + for k in range(1,8): + t=k/8 + center=base+direction*length*t+Vector((0,0,math.sin(t*math.pi)*length*.6)) + for sign in [-1,1]: + end=center+side*sign*length*.25*math.sin(t*math.pi)+direction*length*.09 + i=len(verts) + verts.extend([tuple(center-direction*.025),tuple(end),tuple(center+direction*.08),tuple(center+Vector((0,0,.015)))]) + faces.extend([(i,i+1,i+3),(i+1,i+2,i+3),(i+2,i,i+3),(i+2,i+1,i)]) + mesh_object('Fern_'+str(seed),verts,faces,M['leaf_mid' if seed%2 else 'leaf_light']) + +def ruin_pillar(x,z,height,team,seed): + box('Pillar_Plinth',x,z,.10,1.30,1.30,.38) + box('Pillar_Foot',x,z,.36,1.04,1.04,.16,'brass',.025) + for level in range(int(height/.5)): + box('Pillar_Block',x,z,.63+level*.48,.8,.8,.46,angle=(seed%3-1)*.018) + box('Pillar_Capital',x,z,height+.2,1.06,1.06,.24) + box('Pillar_Cap',x,z,height+.38,.94,.94,.12,'brass',.018) + # Deep vertical grooves and inset illuminated rune bars on all four faces. + for sx,sz in [(1,0),(-1,0),(0,1),(0,-1)]: + for off in [-.21,.21]: + box('Pillar_Groove',x+sx*.408+sz*off,z+sz*.408+sx*off,height*.52+.25,.034 if sx else .065,.065 if sx else .034,height*.63,'brass',.008) + box('Pillar_Inscription',x+sx*.425,z+sz*.425,height*.67,.038 if sx else .095,.095 if sx else .038,.4,'teal' if team==0 else 'coral',.009) + +# A sculpted, continuous ravine. The causeways are flat and above the terrain. +nx,nz=224,256 +verts=[]; faces=[] +for j in range(nz+1): + z=-52+j*104/nz + for i in range(nx+1): + x=-48+i*96/nx + v=noise.noise_vector(Vector((x*.16,z*.12,3))) + river=math.exp(-(abs(x)/3.4)**4) + h=-.42-5.1*river + v.x*.34 + outer=max(0,abs(x)-29)/11 + h+=outer*(1.7+v.y*2.7) + if 3 < abs(x) < 16 and abs(z)<21: h=min(h,-.24) + shore=max(0,min(1,(math.sqrt((x/48)**2+(z/52)**2)-.70)/.27)) + shore=shore*shore*(3-2*shore) + h=h*(1-shore)-5.5*shore + verts.append(p(x,z,h)) +for j in range(nz): + for i in range(nx): + k=j*(nx+1)+i + faces.append((k,k+nx+1,k+nx+2,k+1)) +terrain=mesh_object('Sculpted_River_Gorge',verts,faces,M['soil']) +for face in terrain.data.polygons: face.use_smooth=True +solid=terrain.modifiers.new('Closed bedrock','SOLIDIFY'); solid.thickness=2 +bpy.context.view_layer.objects.active=terrain +bpy.ops.object.modifier_apply(modifier=solid.name) + +for team,c in enumerate([-9,9]): + # Granite retaining wall: jointed masonry above real rock walls. + box('Causeway_Foundation',c,0,-.65,12.6,41,1.1,'cliff',.13) + for side in [-1,1]: + for j in range(21): + z=-20+j*2 + box('Edge_Coping',c+side*6.2,z,-.04,.48,1.94,.26,'limestone',.06) + if j%3==0: + box('Boundary_Socket',c+side*6.18,z,.12,.58,.7,.25,'limestone',.05) + box('Boundary_Inlay',c+side*6.18,z,.25,.12,.40,.02,'teal' if team==0 else 'coral',.008) + # Side buttresses with stepped lower construction. + if j%4==0: + box('Wall_Buttress',c+side*6.4,z,-1.0,.75,1.15,2.4,'limestone',.09) + box('Wall_Buttress_Foot',c+side*6.4,z,-2.15,1,1.4,.3,'limestone',.06) + for j in range(11): + rock('Stratified_Cliff',c+side*6.7,-21+j*4,-2.55,1.05,2.45,2.45,100+team*30+j) + # Quiet broad paving, recessed bevels and minor rotation keep it natural. + for row in range(20): + for col in range(6): + box('Paving',c-5+col*2,-19+row*2,-.082,1.975,1.975,.15,'paving',.018) + # Portals at the arrival end, clear 10m passage under a ruined arch. + for s in [-1,1]: + ruin_pillar(c+s*5.25,-20.7,3.1,team,team*2+s) + for t in range(3): + box('Portal_Corbel',c+s*(5.1-t*.32),-20.7,3.42+t*.26,1.2,1.15,.32,'limestone',.045) + # Tall spire and layered ring patio around the crystal, outside workers. + for radius,height,depth in [(3.8,-.06,.12),(3.5,.025,.055)]: + obj=cylinder('Sanctum_Patio',p(c,18.2,height),radius,depth,M['limestone'],96) + hd_finish(obj,.025,2) + for rad in [3.25,3.5]: hd_ring('Sanctum_Inlay',p(c,18.2,.067),rad,.025,M['brass'],segments=128) + for s in [-1,1]: + ruin_pillar(c+s*4.45,20.6,2.6,team,40+s) + for i in range(8): + x=c-4.2+(i%4)*2.8; z=13.7+(i//4)*2.2 + box('Gatherer_Station',x,z+.55,.05,1.6,1.0,.12,'limestone',.05) + box('Gatherer_Channel',x,z+.55,.12,1.16,.06,.025,'teal' if team==0 else 'coral',.01) + # Rear stairs communicate an entrance without covering the arena. + for step in range(6): box('Sanctum_Stairs',c,21.3+step*.35,-.08-step*.08,5.6,.45,.2,'limestone',.035) + +# Ruined footbridges connect the courtyards over the gorge. +for z in [-22.5,23.6]: + for j in range(13): + x=-5.1+j*.85 + h=.25+math.sin((j/12)*math.pi)*.5 + box('Bridge_Voussoir',x,z,h-.52,.86,2.3,1,'limestone',.075) + box('Bridge_Paving',x,z,h,.83,2.28,.12,'paving',.018) + for side in [-1,1]: + box('Bridge_Parapet',x,z+side*1.2,h+.25,.81,.18,.50,'limestone',.035) + +# Vegetation frames the board; no trees or grass on either gameplay grid. +for i in range(30): + side=-1 if i%2 else 1 + x=side*R.uniform(19.5,29.5); z=R.uniform(-29,29) + tree(x,z,R.uniform(.78,1.35),i+1) +for i in range(100): + x=R.choice([-1,1])*R.uniform(17.0,30); z=R.uniform(-31,31) + rock('Forest_Boulder',x,z,-.1,R.uniform(.25,1.3),R.uniform(.35,1.5),R.uniform(.3,1.1),i) +for i in range(370): + x=R.choice([-1,1])*R.uniform(16.3,29); z=R.uniform(-31,31) + fern(x,z,R.uniform(.30,.85),i) +for i in range(28): + z=R.uniform(-29,29); x=R.choice([-1,1])*R.uniform(2.1,2.9) + rock('River_Bank',x,z,-3.2,R.uniform(.6,1),R.uniform(1,2),R.uniform(1.2,2.8),300+i) +for i in range(14): + x=R.choice([-1,1])*R.uniform(17,22); z=R.uniform(-28,28) + for j in range(3): + box('Fallen_Ruin',x+j*.32,z+j*.42,.12+j*.1,1.5,.8,.55,'limestone',.07,angle=i*.4) + +# Meadow tussocks on the outer banks, absent from all gameplay cells. +verts=[];faces=[] +for i in range(2200): + x=R.choice([-1,1])*R.uniform(16.6,30.5);z=R.uniform(-32,32) + for j in range(5): + h=R.uniform(.13,.38);w=R.uniform(.012,.03);a=R.uniform(0,math.tau) + base=Vector(p(x+R.uniform(-.11,.11),z+R.uniform(-.11,.11),-.24)) + side=Vector((math.cos(a),math.sin(a),0))*w + bend=Vector((math.sin(a),math.cos(a),0))*h*.36 + mid=base+Vector((0,0,h*.56))+bend*.3 + end=base+Vector((0,0,h))+bend + n=len(verts) + verts.extend([tuple(base-side),tuple(base+side),tuple(mid+side*.7),tuple(mid-side*.7),tuple(end),tuple(mid+Vector((0,0,.012)))]) + faces.extend([(n,n+1,n+2,n+3),(n+3,n+2,n+4),(n+1,n,n+5),(n+2,n+1,n+5),(n+4,n+2,n+5),(n+3,n+4,n+5),(n,n+3,n+5)]) +mesh_object('Meadow_11000_Curved_Blades',verts,faces,M['leaf_mid']) + +# Editable source retains every object. Runtime merges by material and chunk +# for culling, greatly reducing the number of draws compared with source parts. +source=PROJECT/'assets-source/phase10/verdant-rift.blend' +bpy.data.libraries.write(str(source),{scene},fake_user=True,compress=True) +objects=[o for o in scene.objects if o.type=='MESH'] +source_count=len(objects) +groups={} +for obj in objects: + center=obj.matrix_world.translation + key=(int(math.floor(center.x/16)),int(math.floor(center.y/16)),obj.data.materials[0].name) + groups.setdefault(key,[]).append(obj) +for key,parts in groups.items(): + bpy.ops.object.select_all(action='DESELECT') + for obj in parts: obj.select_set(True) + bpy.context.view_layer.objects.active=parts[0] + bpy.ops.object.join() + parts[0].name='Chunk_%d_%d_%s'%key +bpy.ops.object.select_all(action='SELECT') +out=PROJECT/'assets/environment/verdant-rift.glb' +bpy.ops.export_scene.gltf(filepath=str(out),export_format='GLB',use_selection=True,export_apply=True,export_yup=True,export_cameras=False,export_lights=False,export_animations=False) +tris=0 +for obj in scene.objects: + if obj.type=='MESH': + obj.data.calc_loop_triangles();tris+=len(obj.data.loop_triangles) +record={'name':'Die grüne Kluft','source_objects':source_count,'runtime_chunks':len(groups),'triangles':tris,'seed':10092026,'blender':bpy.app.version_string,'sha256':hashlib.sha256(out.read_bytes()).hexdigest(),'playable_grids':2,'cell_size_m':2,'grid_cells':[6,8]} +(PROJECT/'assets-source/phase10/environment-manifest.json').write_text(json.dumps(record,indent=2)+'\n') +print('ENVIRONMENT_EXPORTED',json.dumps(record),flush=True) diff --git a/assets-source/phase10/environment-manifest.json b/assets-source/phase10/environment-manifest.json new file mode 100644 index 0000000..dbf0938 --- /dev/null +++ b/assets-source/phase10/environment-manifest.json @@ -0,0 +1,15 @@ +{ + "name": "Die gr\u00fcne Kluft", + "source_objects": 2586, + "runtime_chunks": 62, + "triangles": 1607600, + "seed": 10092026, + "blender": "5.2.1 LTS", + "sha256": "bebe2d4193500df1cf54970adf0e240607430d66e42fd9ab2e67368166a6d052", + "playable_grids": 2, + "cell_size_m": 2, + "grid_cells": [ + 6, + 8 + ] +} diff --git a/assets-source/phase10/finalize_sources.py b/assets-source/phase10/finalize_sources.py new file mode 100644 index 0000000..4fe70f6 --- /dev/null +++ b/assets-source/phase10/finalize_sources.py @@ -0,0 +1,39 @@ +import bpy,json,sys +from pathlib import Path +p=Path(__file__).resolve().parents[2];source=p/'assets-source/phase4' +sys.path.insert(0,str(source/'blender')) +from reference_sculpt_detail import add_offline_materials +for path in sorted((source/'records').glob('*.json')): + record=json.loads(path.read_text()) + if record['faction'] not in ['wurzelbund','glutpakt','rift'] and record['role'] not in ['worker','core']:continue + with bpy.data.libraries.load(record['blend_path'],link=False) as (frm,to):to.scenes=frm.scenes + objects=[o for scene in to.scenes for o in scene.objects if o.type=='MESH'] + add_offline_materials(objects,p) + # Keep source image references relative to the .blend location. + bpy.data.libraries.write(record['blend_path'],set(to.scenes),path_remap='RELATIVE_ALL',fake_user=True,compress=True) + record['offline_sculpt_parts']=sum(bool(o.get('sculpt_surface')) for o in objects) + record['offline_render_triangles']=0 + for obj in objects: + obj.data.calc_loop_triangles();record['offline_render_triangles']+=len(obj.data.loop_triangles)*(16 if obj.get('sculpt_surface') else 1) + path.write_text(json.dumps(record,ensure_ascii=False,indent=2)+'\n') + for scene in to.scenes:bpy.data.scenes.remove(scene) + for obj in objects: + if not obj.users:bpy.data.objects.remove(obj) +from pipeline import write_manifest +write_manifest() +print('BLENDER_PBR_SOURCE_PASS: 33 independent scenes with editable high-resolution geometry and material nodes.') + +# Environment source keeps its original 2586 independently editable objects. +map_path=p/'assets-source/phase10/verdant-rift.blend' +with bpy.data.libraries.load(str(map_path),link=False) as (frm,to):to.scenes=frm.scenes +materials={m for scene in to.scenes for obj in scene.objects if obj.type=='MESH' for m in obj.data.materials if m} +for mat in materials: + if mat.get('phase10_pbr') or not any(k in mat.name for k in ['limestone','cliff','paving']):continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links;bsdf=nodes.get('Principled BSDF') + texture=nodes.new('ShaderNodeTexImage');texture.image=bpy.data.images.load(str(p/'assets/materials/phase10/limestone-albedo.png'),check_existing=True);texture.projection='BOX';texture.projection_blend=.3 + coord=nodes.new('ShaderNodeTexCoord');links.new(coord.outputs['Object'],texture.inputs['Vector']) + bump=nodes.new('ShaderNodeBump');bump.inputs['Strength'].default_value=.3;bump.inputs['Distance'].default_value=.04 + links.new(texture.outputs['Color'],bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True +bpy.data.libraries.write(str(map_path),set(to.scenes),path_remap='RELATIVE_ALL',fake_user=True,compress=True) +print('ENVIRONMENT_PBR_SOURCE_PASS') diff --git a/assets-source/phase10/material-provenance.json b/assets-source/phase10/material-provenance.json new file mode 100644 index 0000000..f55788b --- /dev/null +++ b/assets-source/phase10/material-provenance.json @@ -0,0 +1,22 @@ +{ + "method": "Built-in image_gen (stone); Blender procedural render/bake (oak).", + "stone": { + "file": "assets/materials/phase10/limestone-albedo.png", + "width": 1254, + "height": 1254, + "note": "Tool returned 1254px despite the prompt requesting 4096px. This file is not advertised as 4K." + }, + "oak": { + "files": [ + "assets/materials/phase10/oak-albedo-4k.png", + "assets/materials/phase10/oak-height-4k.png" + ], + "width": 4096, + "height": 4096, + "source": "assets-source/phase10/bake_bark.py", + "note": "Native Blender renders of a periodic 4D-noise material. No bitmap enlargement. 16-bit intermediates retained in assets-source/phase10; 8-bit runtime maps use GPU compression and mipmaps." + }, + "unused_attempt": { + "result": "Image generation service returned usage_limit_reached; no generated bark image used." + } +} diff --git a/assets-source/phase10/oak-albedo-4k-16bit.png b/assets-source/phase10/oak-albedo-4k-16bit.png new file mode 100644 index 0000000..1903b43 Binary files /dev/null and b/assets-source/phase10/oak-albedo-4k-16bit.png differ diff --git a/assets-source/phase10/oak-height-4k-16bit.png b/assets-source/phase10/oak-height-4k-16bit.png new file mode 100644 index 0000000..f80b491 Binary files /dev/null and b/assets-source/phase10/oak-height-4k-16bit.png differ diff --git a/assets-source/phase10/oak-material-4k.blend b/assets-source/phase10/oak-material-4k.blend new file mode 100644 index 0000000..2f6cc22 Binary files /dev/null and b/assets-source/phase10/oak-material-4k.blend differ diff --git a/assets-source/phase10/revisions/before-graphics.tar.gz b/assets-source/phase10/revisions/before-graphics.tar.gz new file mode 100644 index 0000000..0ebdced Binary files /dev/null and b/assets-source/phase10/revisions/before-graphics.tar.gz differ diff --git a/assets-source/phase10/verdant-rift.blend b/assets-source/phase10/verdant-rift.blend new file mode 100644 index 0000000..00f70ee Binary files /dev/null and b/assets-source/phase10/verdant-rift.blend differ diff --git a/assets-source/phase11/bake_cutwood.py b/assets-source/phase11/bake_cutwood.py new file mode 100644 index 0000000..8680d1c --- /dev/null +++ b/assets-source/phase11/bake_cutwood.py @@ -0,0 +1,32 @@ +"""Native 4K PBR maps from an authored annual-ring surface; no bitmap upscaling. +Blender writes portable RGB PNGs. Colour is explicitly encoded as sRGB; the +normal and roughness images contain linear data. All maps share the same UVs. +""" +from pathlib import Path +import bpy,numpy as np,json +P=Path(__file__).resolve().parents[2];out=P/'assets/materials/phase11';out.mkdir(exist_ok=True) +N=4096 +axis=np.linspace(-1,1,N,dtype=np.float32);x=axis[None,:];y=axis[:,None] +r=np.sqrt(x*x+y*y);a=np.arctan2(y,x) +phase=r*12+.13*np.sin(a*3+r*9)+.07*np.sin(a*7-r*8) +edge=np.abs(np.sin(phase*np.pi));line=np.clip((.27-edge)/.15,0,1);line=line*line*(3-2*line) +fibres=np.sin(a*113+r*38)*np.sin(r*290+a*5) +split=np.zeros((N,N),dtype=np.float32) +for k in range(3): + ca=.36+k*2.12;d=np.abs(np.arctan2(np.sin(a-ca-.012*np.sin(r*24)),np.cos(a-ca-.012*np.sin(r*24)))) + split=np.maximum(split,np.clip((.014-d)/.011,0,1)*np.clip((r-(.48+.1*k))/(.91-.48-.1*k),0,1)) +height=.54-.17*line-.35*split+.018*fibres +rgba=np.ones((N,N,4),dtype=np.float32) +def save(name,data,srgb=False): + if data.ndim==2:data=data[:,:,None] + if srgb:data=np.where(data<=.0031308,12.92*data,1.055*np.maximum(data,0)**(1/2.4)-.055) + rgba[:,:,:3]=np.clip(data,0,1) + im=bpy.data.images.new(name,width=N,height=N,alpha=False,float_buffer=False) + im.colorspace_settings.name='Non-Color';im.pixels.foreach_set(rgba.ravel());im.filepath_raw=str(out/(name+'.png'));im.file_format='PNG';im.save();bpy.data.images.remove(im) +colour=(1.2-.64*line)*(1+.07*fibres)*(1-.8*split) +save('ringborke-cut-albedo-4k',colour[:,:,None]*np.array([.265,.147,.066],dtype=np.float32),True) +gy,gx=np.gradient(height);normal=np.dstack((-gx*42,-gy*42,np.ones_like(height)));normal/=np.linalg.norm(normal,axis=2)[:,:,None] +save('ringborke-cut-normal-4k',normal*.5+.5) +save('ringborke-cut-roughness-4k',.78+.14*line+.06*split) +(P/'assets-source/phase11/material-provenance.json').write_text(json.dumps({'method':'Original analytic Blender/Python surface bake','size':[N,N],'upscaled':False,'albedo_encoding':'sRGB','normal_encoding':'linear, tangent space +Y','roughness_encoding':'linear','generator':'assets-source/phase11/bake_cutwood.py','inputs':'Annual ring field, warped fibres and radial growth checks; no external images'},indent=2)+'\n') +print('CUTWOOD_BAKE_PASS: three native 4096px material maps',flush=True) diff --git a/assets-source/phase11/build_ringborke.py b/assets-source/phase11/build_ringborke.py new file mode 100644 index 0000000..991451f --- /dev/null +++ b/assets-source/phase11/build_ringborke.py @@ -0,0 +1,340 @@ +"""Ringborke: authored surfaces, weighted skeleton and portable animation clips. +Blender Z up, -Y forward. Run in a fresh background Blender process. +The existing Phase 4 sources remain intact. No downloaded assets are used. +""" +from pathlib import Path +import bpy, bmesh, math, random, json, hashlib +from mathutils import Vector, Quaternion +from math import sin, cos, pi +P=Path(__file__).resolve().parents[2] +OUT=P/'assets/characters'; OUT.mkdir(exist_ok=True) +SRC=Path(__file__).resolve().parent +random.seed(41) +bpy.ops.wm.read_factory_settings(use_empty=True) +S=.82 +def coord(v): + return Vector((v[0]*1.06,v[1],v[2]*.82 if v[2]<.8 else v[2]-.144))*S +parts=[] + +def material(name, color, rough=.85, bark=False, emission=False): + m=bpy.data.materials.new('RB_'+name);m.diffuse_color=(*color,1);m.use_nodes=True + n=m.node_tree.nodes;l=m.node_tree.links;b=n.get('Principled BSDF');b.inputs['Base Color'].default_value=(*color,1);b.inputs['Roughness'].default_value=rough + if emission: + b.inputs['Emission Color'].default_value=(*color,1);b.inputs['Emission Strength'].default_value=.8 + else: + v=n.new('ShaderNodeVertexColor');v.layer_name='SurfaceColor';l.new(v.outputs['Color'],b.inputs['Base Color']) + if name=='Cutwood': + for suffix,target in [('albedo','Base Color'),('roughness','Roughness'),('normal','Normal')]: + tex=n.new('ShaderNodeTexImage');tex.image=bpy.data.images.load(str(P/('assets/materials/phase11/ringborke-cut-'+suffix+'-4k.png')),check_existing=True) + tex.image.colorspace_settings.name='sRGB' if suffix=='albedo' else 'Non-Color' + if suffix=='normal': + normal=n.new('ShaderNodeNormalMap');normal.inputs['Strength'].default_value=.6;l.new(tex.outputs['Color'],normal.inputs['Color']);l.new(normal.outputs['Normal'],b.inputs[target]) + else:l.new(tex.outputs['Color'],b.inputs[target]) + if bark: + t=n.new('ShaderNodeTexImage');t.image=bpy.data.images.load(str(P/'assets/materials/phase10/oak-height-4k.png'),check_existing=True);t.image.colorspace_settings.name='Non-Color' + bump=n.new('ShaderNodeBump');bump.inputs['Strength'].default_value=.4;bump.inputs['Distance'].default_value=.035;l.new(t.outputs['Color'],bump.inputs['Height']);l.new(bump.outputs['Normal'],b.inputs['Normal']) + return m +M={ + 'bark':material('Bark',(.18,.105,.055),bark=True), + 'heart':material('Heartwood',(.38,.23,.115),bark=True), + 'cut':material('Cutwood',(.55,.35,.17)), + 'dark':material('Crevice',(.052,.035,.018)), + 'moss':material('Moss',(.18,.28,.052)), + 'leaf':material('Leaf',(.31,.40,.085),.72), + 'flower':material('Petal',(.65,.26,.36),.65), + 'eye':material('Saplight',(.35,.85,.06),.5,emission=True)} + +def mesh(name, verts, faces, kind, bone, uv=None, colors=None, weights=None, smooth=True): + me=bpy.data.meshes.new(name);me.from_pydata([coord(v) for v in verts],[],faces);me.update() + ob=bpy.data.objects.new(name,me);bpy.context.collection.objects.link(ob);me.materials.append(M[kind]);parts.append(ob) + for f in me.polygons:f.use_smooth=smooth + tex=me.uv_layers.new(name='UVMap');col=me.color_attributes.new(name='SurfaceColor',type='FLOAT_COLOR',domain='CORNER') + base=M[kind].diffuse_color[:3] + for f in me.polygons: + for li in f.loop_indices: + i=me.loops[li].vertex_index;v=verts[i] + tex.data[li].uv=uv[i] if uv else (v[0]*.7+v[1]*.3,v[2]*.8) + fac=.89+.11*sin(v[0]*19+v[2]*8)+.035*cos(v[1]*71+v[2]*32) + c=colors[i] if colors else tuple(max(.004,x*fac) for x in base) + col.data[li].color=(*c,1) + groups={} + for i in range(len(verts)): + ws=weights[i] if weights else {bone:1.0} + total=sum(ws.values()) + for key,w in ws.items(): + if key not in groups:groups[key]=ob.vertex_groups.new(name=key) + groups[key].add([i],w/total,'REPLACE') + return ob + +def mixweights(t,bones): + if len(bones)==1:return {bones[0]:1} + t=max(0,min(.999999,t))*(len(bones)-1);i=int(t);w=t-i + return {bones[i]:1-w,bones[i+1]:w} + +def tube(name,points,radii,kind,bones,sides=16,steps=32,flatten=1,groove=.08): + """Closed organic sweep, smooth interpolated centerline, longitudinal grain relief.""" + points=[Vector(x) for x in points];vs=[];uv=[];ws=[];loops=[];fs=[] + def point(t): + a=min(len(points)-2,int(t*(len(points)-1)));u=t*(len(points)-1)-a + p0=points[max(a-1,0)];p1=points[a];p2=points[a+1];p3=points[min(a+2,len(points)-1)] + return .5*((2*p1)+(-p0+p2)*u+(2*p0-5*p1+4*p2-p3)*u*u+(-p0+3*p1-3*p2+p3)*u*u*u),radii[a]*(1-u)+radii[a+1]*u + for j in range(steps+1): + t=j/steps;p,r=point(t);tan=(point(min(1,t+.002))[0]-point(max(0,t-.002))[0]).normalized();u=tan.cross(Vector((0,1,0))).normalized();v=tan.cross(u) + loop=[] + for k in range(sides): + a=2*pi*k/sides;mod=1+groove*(sin(a*7+t*3)+.4*sin(a*13-t*9)) + vs.append(p+r*mod*(u*cos(a)+v*sin(a)*flatten));uv.append((k/sides,t*1.7));ws.append(mixweights(t,bones));loop.append(len(vs)-1) + loops.append(loop) + for a,b in zip(loops,loops[1:]): + for k in range(sides):q=(k+1)%sides;fs.append((a[k],a[q],b[q],b[k])) + fs.extend([tuple(reversed(loops[0])),tuple(loops[-1])]) + return mesh(name,vs,fs,kind,bones[0],uv,weights=ws) + +def ell(name,c,r,kind,bone,segments=20,rings=10): + vs=[(c[0],c[1],c[2]+r[2])];fs=[] + for j in range(1,rings): + th=pi*j/rings + for k in range(segments): + a=2*pi*k/segments;f=1+.045*sin(a*5+j*1.7) + vs.append((c[0]+r[0]*sin(th)*cos(a)*f,c[1]+r[1]*sin(th)*sin(a)*f,c[2]+r[2]*cos(th))) + vs.append((c[0],c[1],c[2]-r[2]));end=len(vs)-1 + for k in range(segments):fs.append((0,1+k,1+(k+1)%segments)) + for j in range(rings-2): + for k in range(segments):a=1+j*segments+k;b=1+j*segments+(k+1)%segments;fs.append((a,a+segments,b+segments,b)) + for k in range(segments):fs.append((end,end-1-k,end-1-(k+1)%segments)) + return mesh(name,vs,fs,kind,bone) + +def shield(name,c,rx,rz,depth,bone,angle=0): + # Thick irregular cut log: no raised concentric torus ornaments. + n=96;radial=26;vs=[];uv=[];cols=[];fs=[] + def world(x,y,z):return(c[0]+x*cos(angle)-z*sin(angle),c[1]+y,c[2]+x*sin(angle)+z*cos(angle)) + vs.append(world(0,-depth*.54,0));uv.append((.5,.5));cols.append((.42,.27,.135)) + for j in range(1,radial+1): + r=j/radial + for k in range(n): + a=2*pi*k/n;edge=1+.038*sin(5*a+1.1)+.028*sin(9*a-.4) + rings=r*12+.10*sin(3*a+r*7)+.07*sin(7*a-r*9) + grain=abs(sin(rings*pi));groove=max(0,(.22-grain)/.22) + # Four narrow radial checks, restricted to the edge of the heartwood. + crack=max(max(0,1-abs(math.atan2(sin(a-q),cos(a-q)))/.025) for q in [.35,2.1,3.9,5.6])*max(0,(r-.53)/.47) + y=-depth*.55+.018*r*r+.008*groove+.028*crack + vs.append(world(rx*r*edge*cos(a),y,rz*r*edge*sin(a)));uv.append((.5+.5*r*cos(a),.5+.5*r*sin(a))) + val=(.91-.22*groove-.60*crack)*(1-.12*r) + cols.append(tuple(v*val for v in (.53,.35,.185))) + for k in range(n):fs.append((0,1+(k+1)%n,1+k)) + for j in range(radial-1): + for k in range(n):a=1+j*n+k;b=1+j*n+(k+1)%n;fs.append((a,b,b+n,a+n)) + front=len(vs)-n;back=len(vs) + for k in range(n): + a=2*pi*k/n;e=1+.038*sin(5*a+1.1)+.028*sin(9*a-.4);vs.append(world(rx*.95*e*cos(a),depth*.5,rz*.95*e*sin(a)));uv.append((k/n,0));cols.append((.13,.08,.038)) + for k in range(n):q=(k+1)%n;fs.append((front+k,front+q,back+q,back+k)) + fs.append(tuple(back+k for k in reversed(range(n)))) + ob=mesh(name,vs,[tuple(reversed(f)) for f in fs],'cut',bone,uv,cols) + # Continuous chipped bark mantle around the log; longitudinal ridges, not beads. + vv=[];ff=[];tt=[] + profile=[(.94,-.56),(1.025,-.49),(1.07,-.18),(1.045,.36),(.94,.63),(.87,.42)] + for j,(radius,y) in enumerate(profile): + for k in range(n): + a=2*pi*k/n;edge=1+.038*sin(5*a+1.1)+.028*sin(9*a-.4) + ridge=1+.028*sin(a*19+.4*j)+.015*sin(a*31-.2*j) + vv.append(world(rx*radius*edge*ridge*cos(a),depth*y+.008*sin(a*13),rz*radius*edge*ridge*sin(a))) + tt.append((k/n*2,j/5)) + for j in range(len(profile)): + for k in range(n): + q=(k+1)%n;h=(j+1)%len(profile);ff.append((j*n+k,j*n+q,h*n+q,h*n+k)) + mesh(name+'_BarkMantle',vv,[tuple(reversed(f)) for f in ff],'bark',bone,tt) + return ob + +def leaf(name,start,end,width,bone,kind='leaf'): + a=Vector(start);b=Vector(end);d=b-a;u=d.cross(Vector((0,1,0))).normalized();v=d.normalized().cross(u);vs=[];fs=[] + for side in [-1,1]: + for j in range(9): + t=j/8;w=width*sin(pi*t)**.7 + for k in [-1,0,1]:vs.append(a+d*t+u*w*k+v*(sin(pi*t)*(.025+.028*(1-abs(k))))+Vector((0,side*.003,0))) + for layer in range(2): + for j in range(8): + for k in range(2): + i=layer*27+j*3+k;quad=(i,i+1,i+4,i+3);fs.append(quad if layer else tuple(reversed(quad))) + for j in range(8): + i=j*3;fs.extend([(i,i+3,i+30,i+27),(i+2,i+29,i+32,i+5)]) + fs.extend([(0,27,28,29,2,1),(24,25,26,53,52,51)]) + return mesh(name,vs,fs,kind,bone) + +# Thick connected trunk and flowing, softly weighted fibres around moving joints. +tube('Trunk',[(0,.08,.70),(-.02,.08,1.03),(0,.05,1.42),(0,.06,1.69)],[.28,.36,.46,.30],'bark',['Pelvis','Spine','Chest'],32,52,flatten=.77) +for k in range(11): + a=k*2*pi/11 + tube('Trunk_Rib_%02d'%k,[(.23*cos(a),.08+.22*sin(a),.73),(.30*cos(a+.12),.03+.29*sin(a+.12),1.08),(.41*cos(a-.10),.03+.31*sin(a-.10),1.42),(.22*cos(a),.07+.19*sin(a),1.73)],[.055,.075,.09,.038],'heart' if k%3==0 else 'bark',['Pelvis','Spine','Chest'],10,30,groove=.14) +# Chest shield is recessed between shoulders; the face remains visible above it. +shield('Breast_Heart',(.05,-.365,1.28),.33,.38,.14,'Chest',-.14) +# Neck and carved angular mask, eyebrows and an actual dark recessed face. +tube('Neck',[(0,.07,1.58),(0,-.02,1.86),(.01,-.06,2.05)],[.21,.24,.19],'bark',['Chest','Head'],20,24,flatten=.8) +ell('Face_Recess',(0,-.23,1.90),(.22,.095,.18),'dark','Head') +for s,side in [(-1,'L'),(1,'R')]: + tube('Brow_'+side,[(s*.025,-.332,1.96),(s*.125,-.329,2.025),(s*.24,-.23,2.035)],[.068,.064,.045],'heart',['Head'],8,14,flatten=.7) + tube('Cheek_'+side,[(s*.22,-.245,1.98),(s*.21,-.318,1.88),(s*.12,-.31,1.79)],[.065,.045,.035],'bark',['Head'],8,14) + ell('Eye_'+side,(s*.105,-.326,1.934),(.052,.019,.018),'eye','Head',16,8) +for s,side in [(-1,'L'),(1,'R')]: + vs=[(s*.01,-.34,1.98),(s*.115,-.39,2.04),(s*.25,-.25,2.065),(s*.235,-.30,1.975),(s*.09,-.36,1.967), + (s*.01,-.29,1.98),(s*.115,-.30,2.04),(s*.25,-.18,2.065),(s*.235,-.23,1.975),(s*.09,-.28,1.967)] + fs=[(0,1,2,3,4),(9,8,7,6,5)]+[(k,(k+1)%5,(k+1)%5+5,k+5) for k in range(5)] + mesh('CarvedBrow_'+side,vs,fs if s>0 else [tuple(reversed(f)) for f in fs],'bark','Head',smooth=False) +tube('Nose_Ridge',[(0,-.335,2.01),(0,-.38,1.91),(0,-.35,1.83)],[.038,.051,.028],'heart',['Head'],8,14) +# Crown: tapered broken wood spires and a large asymmetrical rear stump. +shield('Back_Crown',(-.10,.07,1.95),.26,.29,.28,'Chest',-.30) +for k in range(5): + a=k*pi*.4 + tube('Crown_Branch_%d'%k,[(.16*cos(a),.11+.17*sin(a),1.95),(.28*cos(a),.13+.22*sin(a),2.16+(.06 if k%2 else 0)),(.38*cos(a),.16+.27*sin(a),2.29+(k%2)*.11)],[.075,.045,.009],'bark',['Head'],10,16) +for s,side in [(-1,'L'),(1,'R')]: + arm=['UpperArm.'+side,'Forearm.'+side,'Hand.'+side] + tube('Arm_Fibres_'+side,[(s*.39,.04,1.65),(s*.68,.035,1.55),(s*.85,-.045,1.20),(s*.87,-.20,.85),(s*.89,-.24,.68)],[.22,.27,.21,.21,.18],'bark',arm,24,44,flatten=.86) + for k in range(5): + a=2*pi*k/5 + tube('Arm_Rib_'+side+str(k),[(s*.50+.15*cos(a),.04+.15*sin(a),1.62),(s*.78+.16*cos(a),-.02+.16*sin(a),1.28),(s*.88+.15*cos(a),-.17+.15*sin(a),.88)],[.055,.048,.035],'heart' if k==1 else 'bark',arm[:2],9,24) + shield('Shoulder_'+side,(s*.63,-.17,1.60),.36 if s<0 else .30,.39 if s<0 else .33,.20,arm[0],s*-.16) + shield('Forearm_Plate_'+side,(s*.91,-.355,.97),.19,.25,.15,arm[1],s*.16) + ell('Palm_'+side,(s*.88,-.25,.70),(.22,.17,.16),'bark',arm[2]) + for finger in range(3): + x=s*.88+(finger-1)*.12 + tube('Finger_'+side+str(finger),[(x,-.30,.69),(x+s*.035,-.37,.55),(x+s*.03,-.40,.46)],[.065,.052,.027],'heart',[arm[2],'Finger%d.%s'%(finger,side)],10,16) + tube('Thumb_'+side,[(s*.76,-.21,.73),(s*.68,-.35,.65),(s*.71,-.42,.60)],[.075,.053,.026],'bark',[arm[2],'Thumb.'+side],10,16) + leg=['Thigh.'+side,'Shin.'+side,'Foot.'+side] + tube('Leg_'+side,[(s*.24,.07,.86),(s*.34,.035,.64),(s*.42,-.025,.38),(s*.43,-.025,.16)],[.22,.23,.18,.15],'bark',leg,24,42,flatten=.87) + for k in range(4): + a=2*pi*k/4 + tube('Leg_Ridge_'+side+str(k),[(s*.25+.14*cos(a),.05+.13*sin(a),.84),(s*.40+.16*cos(a),.02+.14*sin(a),.43),(s*.46+.14*cos(a),-.04+.12*sin(a),.14)],[.06,.05,.035],'heart' if k==3 else 'bark',leg,9,24) + shield('Knee_'+side,(s*.39,-.19,.43),.14,.16,.08,leg[1],s*.22) + for toe in range(3): + x=s*.43+(toe-1)*.13 + tube('Toe_'+side+str(toe),[(s*.43,-.03,.19),(x,-.20,.10),(x+(toe-1)*.03,-.40,.045)],[.095,.081,.020],'heart',[leg[2],'Toe.'+side],12,22) + tube('Heel_'+side,[(s*.43,.035,.20),(s*.49,.18,.11),(s*.55,.23,.04)],[.095,.064,.015],'bark',[leg[2]],10,14) +# Distinct layered back plates: tangential, following the torso rather than floating discs. +for row in range(4): + for k in range(7): + a=.1+k*pi/6;z=.90+row*.20;r=.31+.07*sin(row/3*pi) + pts=[(r*.84*cos(a),.08+r*.72*sin(a),z-.13),((r+.045)*cos(a),.08+(r+.045)*.75*sin(a),z),((r-.035)*cos(a),.08+(r-.035)*.75*sin(a),z+.19)] + tube('Back_Plate_%d_%d'%(row,k),pts,[.05,.105,.015],'bark',['Spine' if row<2 else 'Chest'],8,16,flatten=.42,groove=.12) +# Moss grows in upper seams. Small leaf clusters make porous growth, never a green body ball. +for j in range(190): + zone=j%3 + if zone==0: + s=-1 if j%2 else 1;c=(s*(.45+random.random()*.25),-.15+random.random()*.25,(1.97 if s<0 else 1.92)+random.random()*.055);bone='UpperArm.'+('L' if s<0 else 'R') + elif zone==1: + a=random.uniform(.15,pi-.15);c=(.34*cos(a),.1+.28*sin(a),random.uniform(1.06,1.65));bone='Chest' + else:c=(random.uniform(-.22,.22),random.uniform(-.03,.25),2.225+random.random()*.04);bone='Head' + ell('Moss_%03d'%j,c,(.045+random.random()*.025,.036,.019),'moss',bone,8,4) +# Small overlapping foliage breaks up the shoulder and torso seams. +for j in range(84): + s=-1 if j%2 else 1 + if j<52: + x=s*random.uniform(.40,.82);y=random.uniform(-.23,.13);z=1.96 if s<0 else 1.91;bone='UpperArm.'+('L' if s<0 else 'R') + else: + x=s*random.uniform(.29,.39);y=-.27;z=random.uniform(.98,1.56);bone='Spine' if z<1.2 else 'Chest' + leaf('SeamLeaf_%02d'%j,(x,y,z),(x+s*.065,y-.045,z+random.uniform(.035,.095)),random.uniform(.025,.048),bone,'moss') +for j in range(32): + s=-1 if j%2 else 1;bone='Head' if j<14 else 'Chest';z=2.15 if j<14 else 1.49;x=s*(.19+random.random()*.14);y=.11 if j<14 else .24 + leaf('Sprout_%02d'%j,(x,y,z),(x+s*random.uniform(.08,.19),y-.07,z+random.uniform(.10,.24)),random.uniform(.03,.055),bone) +for j,(x,y,z,bone) in enumerate([(-.46,-.21,1.93,'UpperArm.L'),(.54,-.23,1.83,'UpperArm.R'),(-.23,-.28,1.41,'Chest'),(.26,-.29,1.57,'Chest')]): + for k in range(5): + a=2*pi*k/5;leaf('Blossom_%d_%d'%(j,k),(x+.007*cos(a),y,z+.007*sin(a)),(x+.045*cos(a),y-.015,z+.045*sin(a)),.014,bone,'flower') + ell('BlossomHeart'+str(j),(x,y-.014,z),(.009,.009,.009),'cut',bone,8,4) + +# Weld closed leaf tips and consistently orient every disconnected solid before skinning. +# BMesh preserves UV corners, colours and deform groups during this cleanup. +for ob in parts: + bm=bmesh.new();bm.from_mesh(ob.data) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.0000005) + bmesh.ops.triangulate(bm,faces=list(bm.faces)) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.0000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + if bm.calc_volume(signed=True)<0:bmesh.ops.reverse_faces(bm,faces=list(bm.faces)) + bm.to_mesh(ob.data);bm.free();ob.data.update() + +# Skeleton, anatomically placed hinges. Flexible fibre meshes blend adjacent joints. +bpy.ops.object.armature_add(enter_editmode=True);rig=bpy.context.object;rig.name='RingborkeRig';ed=rig.data.edit_bones;ed.remove(ed[0]);defs={} +def bone(name,head,tail,parent=None): + b=ed.new(name);b.head=coord(head);b.tail=coord(tail) + if parent:b.parent=ed[parent] + defs[name]=(head,tail,parent) +bone('Root',(0,0,0),(0,0,.2));bone('Pelvis',(0,.06,.72),(0,.05,1.02),'Root');bone('Spine',(0,.05,1.02),(0,.05,1.38),'Pelvis');bone('Chest',(0,.05,1.38),(0,.02,1.72),'Spine');bone('Head',(0,.02,1.72),(0,-.02,2.15),'Chest') +for s,side in [(-1,'L'),(1,'R')]: + bone('UpperArm.'+side,(s*.47,.04,1.63),(s*.84,-.04,1.19),'Chest');bone('Forearm.'+side,(s*.84,-.04,1.19),(s*.88,-.24,.73),'UpperArm.'+side);bone('Hand.'+side,(s*.88,-.24,.73),(s*.88,-.35,.59),'Forearm.'+side) + for f in range(3): + x=s*.88+(f-1)*.12;bone('Finger%d.%s'%(f,side),(x,-.32,.66),(x+s*.03,-.40,.46),'Hand.'+side) + bone('Thumb.'+side,(s*.76,-.21,.73),(s*.71,-.42,.60),'Hand.'+side) + bone('Thigh.'+side,(s*.25,.06,.79),(s*.41,-.02,.42),'Pelvis');bone('Shin.'+side,(s*.41,-.02,.42),(s*.43,-.02,.15),'Thigh.'+side);bone('Foot.'+side,(s*.43,-.02,.15),(s*.43,-.25,.07),'Shin.'+side);bone('Toe.'+side,(s*.43,-.25,.07),(s*.43,-.43,.045),'Foot.'+side) +bpy.ops.object.mode_set(mode='OBJECT') +for ob in parts: + mod=ob.modifiers.new('Weighted living wood','ARMATURE');mod.object=rig;ob.parent=rig +# Bake explicit character poses into editable actions at 30fps. Global axes are +# converted to each bone's rest basis. Imported engine clips need no Python. +clips={'idle':(3.2,True),'start':(.4,False),'walk':(1.4,True),'stop':(.4,False),'attack_a':(1.25,False),'attack_b':(1.25,False),'hit':(.48,False),'ability':(1.8,False),'death':(2.1,False)} +def curve(t,keys): + for i in range(len(keys)-1): + a,x=keys[i];b,y=keys[i+1] + if t<=b: + u=max(0,(t-a)/(b-a));u=u*u*(3-2*u);return x*(1-u)+y*u + return keys[-1][1] +def animate(name,t,dur): + rotations={};locs={} + def rot(b,x=0,y=0,z=0):rotations[b]=(x,y,z) + if name=='idle': + q=sin(2*pi*t/dur);rot('Spine',.012*q);rot('Chest',-.018*q,0,.009*q);rot('Head',.016*q,0,-.015*q) + for s,side in [(-1,'L'),(1,'R')]:rot('Forearm.'+side,.013*q,0,s*.007*q) + elif name in ('walk','start','stop'): + fade=1 if name=='walk' else sin(pi*.5*t/dur) if name=='start' else cos(pi*.5*t/dur) + phase=t/1.4*2*pi;roll=sin(phase)*fade + rot('Pelvis',.015,0,.035*roll);rot('Spine',-.045*fade,0,-.05*roll);rot('Chest',.018*fade,0,.025*roll);rot('Head',.035*fade,0,-.02*roll) + for s,side in [(-1,'L'),(1,'R')]: + q=sin(phase+(0 if s<0 else pi));lift=max(0,q);rot('Thigh.'+side,.34*q*fade);rot('Shin.'+side,-.40*lift*fade);rot('Foot.'+side,(-.34*q+.40*lift)*fade);rot('Toe.'+side,.12*max(0,-q)*fade) + rot('UpperArm.'+side,-.13*q*fade,0,s*.02*fade);rot('Forearm.'+side,-.045*fade-.025*lift) + locs['Root']=(0,0,(-.012+.012*cos(phase*2))*fade) + elif name.startswith('attack'): + # Contact is at normalized attack progress 0.72, aligned by runtime to damage. + q=curve(t/dur,[(0,0),(.32,-.35),(.54,-.55),(.72,1),(.80,.85),(1,0)]) + left=name=='attack_a';side='L' if left else 'R';other='R' if left else 'L';s=-1 if left else 1 + rot('Spine',-.11*q,0,s*.09*q);rot('Chest',-.10*q,0,s*.14*q);rot('Head',.09*q,0,-s*.10*q) + rot('UpperArm.'+side,-.88*q,(-.14 if left else .08)*q,s*.13*q);rot('Forearm.'+side,-.20*q);rot('Hand.'+side,.16*q);rot('UpperArm.'+other,.11*q,0,-s*.10*q) + for f in range(3):rot('Finger%d.%s'%(f,side),-.25*max(0,q)) + rot('Thigh.'+side,.06*q);rot('Shin.'+side,-.06*q);locs['Root']=(0,-.04*q,-.015*max(0,q)) + elif name=='hit': + q=curve(t,[(0,0),(.08,1),(.22,.5),(.48,0)]);rot('Spine',.12*q,0,-.08*q);rot('Head',.13*q,0,.06*q);rot('Forearm.L',-.10*q);rot('Forearm.R',-.08*q) + elif name=='ability': + q=curve(t,[(0,0),(.35,.5),(.75,1),(1.15,.85),(1.8,0)]);rot('Spine',.08*q);rot('Chest',.10*q);rot('Head',-.15*q) + for s,side in [(-1,'L'),(1,'R')]:rot('UpperArm.'+side,-.22*q,0,s*.38*q);rot('Forearm.'+side,-.32*q);rot('Hand.'+side,.15*q) + elif name=='death': + q=curve(t,[(0,0),(.2,.05),(.7,.38),(1.30,1),(1.55,.93),(2.1,1)]) + rot('Root',-.95*q,0,.13*q);locs['Root']=(0,-.15*q,-.12*q);rot('Pelvis',-.22*q);rot('Spine',-.24*q);rot('Head',-.20*q) + for s,side in [(-1,'L'),(1,'R')]:rot('UpperArm.'+side,-.32*q,0,s*.17*q);rot('Forearm.'+side,-.50*q);rot('Thigh.'+side,.26*q);rot('Shin.'+side,-.44*q) + for pb in rig.pose.bones: + pb.rotation_mode='QUATERNION';r=rotations.get(pb.name,(0,0,0));q=Quaternion((0,0,1),r[2])@Quaternion((0,1,0),r[1])@Quaternion((1,0,0),r[0]);basis=pb.bone.matrix_local.to_quaternion();pb.rotation_quaternion=basis.inverted()@q@basis + pb.location=pb.bone.matrix_local.to_3x3().inverted()@(Vector(locs.get(pb.name,(0,0,0)))*S) +for name,(dur,loop) in clips.items(): + rig.animation_data_clear();action=bpy.data.actions.new(name);action.use_fake_user=True;rig.animation_data_create();rig.animation_data.action=action + for frame in range(round(dur*30)+1): + animate(name,frame/30,dur) + for pb in rig.pose.bones:pb.keyframe_insert('rotation_quaternion',frame=frame);pb.keyframe_insert('location',frame=frame) + action['loop']=loop +rig.animation_data_clear() +rig.animation_data_create() +rig.animation_data.action=bpy.data.actions['idle'] +for pb in rig.pose.bones:pb.rotation_quaternion=Quaternion();pb.location=(0,0,0) +bpy.context.scene.render.fps=30;bpy.context.scene.frame_set(0) +# Save the editable source with separate parts and material nodes before export joining. +bpy.ops.wm.save_as_mainfile(filepath=str(SRC/'ringborke.blend')) +bpy.ops.file.make_paths_relative() +bpy.ops.wm.save_as_mainfile(filepath=str(SRC/'ringborke.blend')) +bpy.ops.object.select_all(action='DESELECT') +for ob in parts:ob.select_set(True) +bpy.context.view_layer.objects.active=parts[0];bpy.ops.object.join();body=bpy.context.object;body.name='RingborkeBody' +# One skinned mesh; material surfaces and bone weights remain separate and portable. +body.select_set(True);rig.select_set(True);bpy.context.view_layer.objects.active=rig +bpy.ops.export_scene.gltf(filepath=str(OUT/'ringborke.glb'),export_format='GLB',use_selection=True,export_animations=True,export_animation_mode='ACTIONS',export_force_sampling=True,export_frame_range=False,export_anim_slide_to_zero=True,export_skins=True,export_all_influences=False,export_def_bones=True,export_anim_single_armature=True,export_materials='EXPORT',export_yup=True) +raw=(OUT/'ringborke.glb').read_bytes();import struct +doc=json.loads(raw[20:20+struct.unpack_from(' .94 else Vector((0, 1, 0)) + u = tan.cross(axis).normalized() + v = tan.cross(u) + loop = [] + for k in range(sides): + a = 2 * pi * k / sides + mod = 1 + groove * (sin(a * 5 + t * 4) + .3 * sin(a * 9 - t * 6)) + vs.append(p + r * mod * (u * cos(a) + v * sin(a) * flatten)) + uv.append((k / sides, t)) + ws.append(mixweights(t, bones)) + loop.append(len(vs) - 1) + loops.append(loop) + for a, b in zip(loops, loops[1:]): + for k in range(sides): + q = (k + 1) % sides + fs.append((a[k], a[q], b[q], b[k])) + fs.extend([tuple(reversed(loops[0])), tuple(loops[-1])]) + return mesh(name, vs, fs, kind, bones[0], uv, weights=ws) + +def ell(name, c, r, kind, bone, segments=14, rings=8): + vs = [(c[0], c[1], c[2] + r[2])] + fs = [] + for j in range(1, rings): + th = pi * j / rings + for k in range(segments): + a = 2 * pi * k / segments + f = 1 + .03 * sin(a * 4 + j) + vs.append((c[0] + r[0] * sin(th) * cos(a) * f, c[1] + r[1] * sin(th) * sin(a) * f, c[2] + r[2] * cos(th))) + vs.append((c[0], c[1], c[2] - r[2])) + end = len(vs) - 1 + for k in range(segments): + fs.append((0, 1 + k, 1 + (k + 1) % segments)) + for j in range(rings - 2): + for k in range(segments): + a = 1 + j * segments + k + b = 1 + j * segments + (k + 1) % segments + fs.append((a, a + segments, b + segments, b)) + for k in range(segments): + fs.append((end, end - 1 - k, end - 1 - (k + 1) % segments)) + return mesh(name, vs, fs, kind, bone) + +def box(name, c, size, kind, bone, rot_y=0.0, smooth=False): + sx, sy, sz = size[0] * .5, size[1] * .5, size[2] * .5 + local = [(-sx, -sy, -sz), (sx, -sy, -sz), (sx, sy, -sz), (-sx, sy, -sz), + (-sx, -sy, sz), (sx, -sy, sz), (sx, sy, sz), (-sx, sy, sz)] + ca, sa = cos(rot_y), sin(rot_y) + vs = [(c[0] + x * ca - z * sa, c[1] + y, c[2] + x * sa + z * ca) for x, y, z in local] + faces = [(0, 1, 2, 3), (4, 7, 6, 5), (0, 4, 5, 1), (1, 5, 6, 2), (2, 6, 7, 3), (3, 7, 4, 0)] + return mesh(name, vs, faces, kind, bone, smooth=smooth) + +def frame(name, c, w, h, depth, kind, bone): + """Open rectangular frame for the spark reservoir.""" + t = .018 + box(name + '_T', (c[0], c[1], c[2] + h * .5), (w, depth, t), kind, bone) + box(name + '_B', (c[0], c[1], c[2] - h * .5), (w, depth, t), kind, bone) + box(name + '_L', (c[0] - w * .5, c[1], c[2]), (t, depth, h), kind, bone) + box(name + '_R', (c[0] + w * .5, c[1], c[2]), (t, depth, h), kind, bone) + +def fabric(name, rows, kind, bones, depth=.012, folds=.008, cols=18): + """Tailored closed panel: (height, half-width, front, curvature) rows. + + The two surfaces, side welt and blended weights form one deforming garment; + folds are geometric, so the silhouette survives export without shader tricks. + """ + vs, fs, ws, uv = [], [], [], [] + for back in (0, 1): + for j, (z, width, front, curve) in enumerate(rows): + t = j / (len(rows) - 1) + for k in range(cols + 1): + u = k / cols * 2 - 1 + y = front + curve * u * u + folds * sin(u * pi * 3 + t) * sin(pi * t) + vs.append((u * width, y + back * depth, z + .008 * cos(u * pi) * t)) + ws.append(mixweights(t, bones)); uv.append((k / cols, 1-t)) + stride = cols + 1; layer = len(rows) * stride + for back in (0, 1): + for j in range(len(rows) - 1): + for k in range(cols): + a = back * layer + j * stride + k + q = (a, a+1, a+stride+1, a+stride) + fs.append(q if back else tuple(reversed(q))) + boundary = list(range(stride)) + [j*stride+cols for j in range(1,len(rows))] + boundary += list(range(layer-2,layer-stride-1,-1)) + [j*stride for j in range(len(rows)-2,0,-1)] + for a,b in zip(boundary, boundary[1:]+boundary[:1]): + fs.append((a,b,b+layer,a+layer)) + return mesh(name, vs, fs, kind, bones[0], uv, weights=ws) + +def boot(name, s, side): + """Rounded last, broad sole and fitted ankle rather than stacked cubes.""" + bone = 'Foot.' + side + ell(name, (s*.13,-.053,.071), (.087,.145,.068), 'boot', bone, 24, 10) + # A closed, flattened swept sole has a real broad contact surface. + vs, fs = [], [] + for z, scale in [(0.006,.96),(.018,1),(.037,.97)]: + for k in range(32): + a = 2*pi*k/32 + vs.append((s*.13 + .086*cos(a)*scale,-.055+.147*sin(a)*scale,z)) + for j in range(2): + for k in range(32): + q=(k+1)%32;fs.append((j*32+k,j*32+q,(j+1)*32+q,(j+1)*32+k)) + fs += [tuple(reversed(range(32))),tuple(range(64,96))] + mesh('Sole_'+side,vs,fs,'darkmetal',bone) + tube('Ankle_'+side,[(s*.13,-.01,.06),(s*.125,-.008,.14),(s*.12,-.003,.19)],[.068,.076,.071],'boot',['Foot.'+side,'Shin.'+side],18,14,flatten=.91,groove=.01) + tube('Cuff_'+side,[(s*.125,-.008,.151),(s*.12,-.003,.182)],[.080,.077],'leather',['Shin.'+side],18,6,flatten=.91,groove=.01) + for z in [.080,.099,.118]: + tube('Lace_'+side+str(z),[(s*.13-.04,-.141,z),(s*.13,-.153,z+.007),(s*.13+.04,-.141,z)],[.005,.006,.005],'leather',[bone],6,8,groove=0) + +# ---- Body: stocky gatherer, readable silhouette from all sides ---- +tube('Tunic',[(0,.015,.40),(0,.015,.51),(0,.018,.65),(0,.016,.77),(0,.01,.82)],[.175,.204,.206,.184,.119],'cloth',['Pelvis','Spine','Chest'],28,32,flatten=.77,groove=.018) +fabric('Apron',[(.735,.095,-.153,.021),(.70,.112,-.166,.019),(.63,.154,-.172,.026),(.54,.179,-.182,.033),(.45,.173,-.175,.031),(.36,.163,-.166,.021),(.285,.148,-.16,.017)],'leather',['Chest','Spine','Pelvis'],depth=.014,folds=.012) +for s, side in [(-1,'L'),(1,'R')]: + tube('ApronWelt_'+side,[(s*.094,-.155,.737),(s*.112,-.149,.70),(s*.154,-.148,.63),(s*.179,-.151,.54),(s*.173,-.146,.45),(s*.163,-.147,.36),(s*.148,-.147,.285)],[.005]*7,'boot',['Chest','Spine','Pelvis'],6,30,groove=0) + tube('Harness_'+side,[(s*.085,-.155,.728),(s*.13,-.115,.805),(s*.145,.002,.84),(s*.13,.14,.785),(s*.105,.179,.59)],[.026,.025,.025,.023,.022],'leather',['Chest'],12,28,flatten=.28,groove=0) + ell('ApronRivet_'+side,(s*.084,-.163,.716),(.009,.006,.009),'brass','Chest',10,5) + for j in range(8): + z=.31+j*.035;x=s*(.151+.020*sin((z-.31)*9)) + tube('ApronStitch_'+side+str(j),[(x,-.152,z),(x,-.154,z+.009)],[.0017,.0017],'brass',['Pelvis' if z<.48 else 'Spine'],5,2,groove=0) +tube('ApronHem',[(-.148,-.147,.285),(-.07,-.17,.291),(0,-.163,.293),(.07,-.167,.291),(.148,-.147,.285)],[.006]*5,'boot',['Pelvis'],8,26,groove=0) +# Curved chest pocket and stitched flap conform to the belly. +pocket=fabric('ToolPocket',[(.535,.067,-.20,.012),(.50,.070,-.219,.016),(.455,.062,-.221,.014),(.443,.046,-.208,.010)],'leather',['Spine','Pelvis'],depth=.008,folds=.002,cols=12) +for v in pocket.data.vertices:v.co.x+=.058 +tube('PocketLip',[(0,-.197,.535),(.055,-.208,.538),(.12,-.195,.535)],[.005,.006,.005],'boot',['Spine'],8,14,groove=0) +for s in [-1,1]: + tube('Belt_'+str(s),[(0,-.178,.545),(s*.18,-.119,.548),(s*.204,.045,.555),(s*.14,.166,.565),(0,.178,.565)],[.016]*5,'leather',['Spine'],12,25,flatten=.44,groove=0) + +# Framed glass reservoir on the back for gathered sparks. +frame('ReservoirFrame', (0, .22, .72), .28, .34, .16, 'brass', 'Chest') +box('ReservoirGlass', (0, .22, .72), (.24, .12, .30), 'glass', 'Chest') +ell('ReservoirLiquid', (0, .20, .64), (.10, .05, .08), 'spark', 'Chest', 10, 6) +for k, z in enumerate([.58, .72, .86]): + box('ReservoirBrace_%d' % k, (0, .22, z), (.30, .17, .025), 'brass', 'Chest') + +# Head: hood, lamp, goggles, recessed face. +ell('Neck', (0, .01, .875), (.075, .077, .088), 'skin', 'Head',20,10) +tube('Collar',[(0,.015,.818),(0,.008,.868)],[.112,.094],'hood',['Chest','Head'],24,10,flatten=.79,groove=.014) +ell('Head', (0, -.014, 1.008), (.127, .128, .167), 'skin', 'Head',24,14) +ell('Hood', (0, .040, 1.032), (.155, .154, .190), 'hood', 'Head',24,14) +ell('FaceRecess', (0, -.115, .997), (.112, .058, .12), 'boot', 'Head',24,12) +ell('Face', (0, -.14, 1.00), (.090, .051, .108), 'skin', 'Head',24,12) +ell('Chin', (0, -.140, .931), (.064, .043, .040), 'skin', 'Head',16,8) +for s, side in [(-1,'L'),(1,'R')]: + tube('HoodWelt_'+side,[(s*.03,-.100,.889),(s*.115,-.125,.956),(s*.127,-.139,1.041),(s*.096,-.119,1.115)],[.011,.017,.013,.012],'cloth',['Head'],10,18,groove=.015) + ell('Cheek_'+side,(s*.065,-.162,.986),(.038,.031,.045),'skin','Head',16,8) +for s, side in [(-1, 'L'), (1, 'R')]: + ell('GoggleSocket_' + side, (s * .07, -.15, 1.05), (.05, .03, .04), 'darkmetal', 'Head', 10, 6) + ell('GoggleLens_' + side, (s * .07, -.17, 1.05), (.038, .018, .03), 'lens', 'Head', 10, 6) + ell('GoggleGlint_' + side, (s * .055, -.185, 1.06), (.01, .006, .008), 'lamp', 'Head', 8, 4) +box('GoggleBridge', (0, -.16, 1.05), (.05, .03, .025), 'darkmetal', 'Head') +ell('Cap', (0, .020, 1.135), (.158, .162, .086), 'cloth', 'Head',28,12) +fabric('CapPeak',[(1.133,.135,-.072,.015),(1.125,.163,-.14,.009),(1.108,.164,-.196,.018),(1.102,.129,-.222,.024)],'hood',['Head'],depth=.013,folds=.001,cols=24) +tube('CapSeam',[(-.151,.022,1.153),(-.098,.018,1.197),(0,.010,1.221),(.101,.018,1.197),(.151,.022,1.153)],[.004]*5,'hood',['Head'],6,26,groove=0) +tube('LampHousing',[(0,-.101,1.17),(0,-.158,1.17)],[.045,.044],'brass',['Head'],20,8,groove=0) +ell('Lamp', (0, -.171, 1.17), (.034, .014, .034), 'lamp', 'Head', 20, 8) +ell('Nose',(0,-.188,1.006),(.021,.031,.030),'skin','Head',14,8) +tube('Mouth',[(-.030,-.185,.957),(0,-.188,.953),(.030,-.185,.957)],[.0025,.003,.0025],'boot',['Head'],6,10,groove=0) + +# Arms, gloves, fingers and tools. +for s, side in [(-1, 'L'), (1, 'R')]: + arm = ['UpperArm.' + side, 'Forearm.' + side, 'Hand.' + side] + tube('Sleeve_' + side, [(s*.17,.01,.797),(s*.24,.00,.75),(s*.30,-.02,.64),(s*.33,-.075,.54),(s*.34,-.10,.478)], [.08,.088,.073,.072,.057], 'cloth', [arm[0], arm[1]], 18, 32,groove=.018) + ell('ElbowPatch_' + side, (s * .311, .014, .644), (.068, .048, .071), 'leather', arm[1], 14, 8) + tube('SleeveCuff_'+side,[(s*.332,-.083,.523),(s*.341,-.103,.482)],[.066,.062],'leather',[arm[1]],18,8,groove=.014) + ell('Glove_' + side, (s * .348, -.12, .44), (.067, .055, .064), 'glove', arm[2],20,10) + for finger in range(3): + z=.432-finger*.029; hx=s*(.345+finger*.006) + tube('Finger_%s%d' % (side, finger), [(hx+s*.047,-.119,z+.002),(hx+s*.050,-.151,z),(hx+s*.024,-.177,z-.006),(hx-s*.010,-.173,z-.012)], [.016,.018,.015,.010], 'glove', [arm[2], 'Finger%d.%s' % (finger, side)], 10, 14,groove=.014) + tube('Thumb_' + side, [(s*.306,-.109,.459),(s*.310,-.158,.438),(s*.341,-.174,.429)], [.026,.020,.014], 'glove', [arm[2], 'Thumb.' + side], 10, 14,groove=.014) + +# Left: gathering fork. Right: slender probe. +tube('ForkHandle', [(-.35, -.14, .40), (-.38, -.22, .22), (-.40, -.26, .08)], [.025, .022, .02], 'leather', ['Hand.L'], 8, 12) +for tine in range(3): + x = -.40 + (tine - 1) * .045 + tube('ForkTine_%d' % tine, [(x, -.26, .08), (x, -.30, -.02), (x, -.28, -.10)], [.014, .012, .004], 'metal', ['Hand.L'], 8, 10) +box('ForkGuard', (-.40, -.25, .10), (.14, .04, .03), 'brass', 'Hand.L') +tube('Probe', [(.35, -.14, .40), (.38, -.20, .24), (.40, -.22, .12)], [.018, .014, .008], 'metal', ['Hand.R'], 8, 10) +ell('ProbeTip', (.40, -.23, .10), (.018, .018, .02), 'spark', 'Hand.R', 8, 4) + +# Legs and boots with cuffs and toe ridges. +for s, side in [(-1, 'L'), (1, 'R')]: + leg = ['Thigh.' + side, 'Shin.' + side, 'Foot.' + side] + tube('Trousers_' + side, [(s*.10,.01,.435),(s*.113,.005,.32),(s*.12,0,.24),(s*.13,-.01,.15)], [.095,.098,.078,.068], 'cloth', [leg[0],leg[1]], 18, 26,groove=.018) + ell('KneePatch_'+side,(s*.12,-.066,.25),(.058,.027,.067),'leather',leg[1],14,8) + boot('Boot_'+side,s,side) + +# Weld, triangulate and orient closed solids before skinning. +for ob in parts: + bm = bmesh.new() + bm.from_mesh(ob.data) + bmesh.ops.remove_doubles(bm, verts=list(bm.verts), dist=.0000005) + bmesh.ops.triangulate(bm, faces=list(bm.faces)) + bmesh.ops.dissolve_degenerate(bm, edges=list(bm.edges), dist=.0000001) + bmesh.ops.recalc_face_normals(bm, faces=list(bm.faces)) + if bm.calc_volume(signed=True) < 0: + bmesh.ops.reverse_faces(bm, faces=list(bm.faces)) + bm.to_mesh(ob.data) + bm.free() + ob.data.update() + +# Skeleton: anatomically placed hinges for a compact gatherer. +bpy.ops.object.armature_add(enter_editmode=True) +rig = bpy.context.object +rig.name = 'ArbeiterRig' +ed = rig.data.edit_bones +ed.remove(ed[0]) +defs = {} + +def bone(name, head, tail, parent=None): + b = ed.new(name) + b.head = coord(head) + b.tail = coord(tail) + if parent: + b.parent = ed[parent] + defs[name] = (head, tail, parent) + +bone('Root', (0, 0, 0), (0, 0, .12)) +bone('Pelvis', (0, .01, .40), (0, .02, .58), 'Root') +bone('Spine', (0, .02, .58), (0, .02, .74), 'Pelvis') +bone('Chest', (0, .02, .74), (0, .01, .88), 'Spine') +bone('Head', (0, .01, .88), (0, 0, 1.16), 'Chest') +for s, side in [(-1, 'L'), (1, 'R')]: + bone('UpperArm.' + side, (s * .20, .01, .78), (s * .30, -.02, .64), 'Chest') + bone('Forearm.' + side, (s * .30, -.02, .64), (s * .34, -.10, .48), 'UpperArm.' + side) + bone('Hand.' + side, (s * .34, -.10, .48), (s * .35, -.15, .38), 'Forearm.' + side) + for f in range(3): + x = s * .35 + (f - 1) * .035 + bone('Finger%d.%s' % (f, side), (x, -.15, .40), (x + s * .01, -.19, .33), 'Hand.' + side) + bone('Thumb.' + side, (s * .30, -.10, .44), (s * .27, -.17, .37), 'Hand.' + side) + bone('Thigh.' + side, (s * .10, .01, .42), (s * .12, 0, .24), 'Pelvis') + bone('Shin.' + side, (s * .12, 0, .24), (s * .13, -.01, .08), 'Thigh.' + side) + bone('Foot.' + side, (s * .13, -.01, .08), (s * .13, -.16, .03), 'Shin.' + side) + bone('Toe.' + side, (s * .13, -.16, .03), (s * .13, -.20, .03), 'Foot.' + side) +bpy.ops.object.mode_set(mode='OBJECT') +for ob in parts: + mod = ob.modifiers.new('Weighted gatherer', 'ARMATURE') + mod.object = rig + ob.parent = rig + +# Pose clips at 30 fps. Work cycle: strike (tool contact) → pickup → deposit → return. +clips = { + 'idle': (2.8, True), + 'start': (.35, False), + 'walk': (1.1, True), + 'stop': (.35, False), + 'strike': (1.30, False), + 'pickup': (1.15, False), + 'deposit': (1.20, False), + 'return': (.95, False), + 'hit': (.42, False), + 'death': (1.9, False), +} + +def curve(t, keys): + for i in range(len(keys) - 1): + a, x = keys[i] + b, y = keys[i + 1] + if t <= b: + u = max(0, (t - a) / (b - a)) + u = u * u * (3 - 2 * u) + return x * (1 - u) + y * u + return keys[-1][1] + +def animate(name, t, dur): + rotations = {} + locs = {} + + def rot(b, x=0, y=0, z=0): + rotations[b] = (x, y, z) + + if name == 'idle': + q = sin(2 * pi * t / dur) + rot('Spine', .01 * q) + rot('Chest', -.014 * q, 0, .008 * q) + rot('Head', .02 * q, 0, -.012 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('Forearm.' + side, .02 * q, 0, s * .01 * q) + rot('Finger0.' + side, .04 * q) + elif name in ('walk', 'start', 'stop'): + fade = 1 if name == 'walk' else sin(pi * .5 * t / dur) if name == 'start' else cos(pi * .5 * t / dur) + phase = t / 1.1 * 2 * pi + roll = sin(phase) * fade + rot('Pelvis', .01, 0, .03 * roll) + rot('Spine', -.03 * fade, 0, -.04 * roll) + rot('Chest', .012 * fade, 0, .02 * roll) + rot('Head', .02 * fade, 0, -.015 * roll) + for s, side in [(-1, 'L'), (1, 'R')]: + q = sin(phase + (0 if s < 0 else pi)) + lift = max(0, q) + rot('Thigh.' + side, .28 * q * fade) + rot('Shin.' + side, -.34 * lift * fade) + rot('Foot.' + side, (-.28 * q + .34 * lift) * fade) + rot('Toe.' + side, .10 * max(0, -q) * fade) + rot('UpperArm.' + side, -.08 * q * fade, 0, s * .03 * fade) + rot('Forearm.' + side, -.12 * fade - .04 * lift) + # Reservoir lag: chest sways against the carried load. + locs['Root'] = (0, 0, (-.008 + .008 * cos(phase * 2)) * fade) + elif name == 'strike': + # Contact at 0.62 — the fork tip reaches the ore at the damage frame. + q = curve(t / dur, [(0, 0), (.28, -.40), (.48, -.62), (.62, 1), (.72, .82), (1, 0)]) + rot('Spine', -.14 * q, .08 * q, .06 * q) + rot('Chest', -.10 * q, .06 * q, .10 * q) + rot('Head', .12 * q, -.05 * q, -.06 * q) + rot('UpperArm.L', -.95 * q, -.10 * q, .12 * q) + rot('Forearm.L', -.35 * q) + rot('Hand.L', .22 * q) + rot('UpperArm.R', .18 * q, 0, -.08 * q) + rot('Forearm.R', -.15 * q) + for f in range(3): + rot('Finger%d.L' % f, -.30 * max(0, q)) + rot('Thigh.L', .08 * q) + rot('Thigh.R', -.04 * q) + locs['Root'] = (0, -.03 * q, -.01 * max(0, q)) + elif name == 'pickup': + q = curve(t / dur, [(0, 0), (.35, 1), (.70, .85), (1, 0)]) + rot('Spine', .38 * q) + rot('Chest', .22 * q) + rot('Head', .18 * q) + rot('Thigh.L', .32 * q) + rot('Thigh.R', .28 * q) + rot('Shin.L', -.48 * q) + rot('Shin.R', -.42 * q) + rot('Foot.L', .20 * q) + rot('Foot.R', .18 * q) + rot('UpperArm.L', -.55 * q, 0, .18 * q) + rot('Forearm.L', -.40 * q) + rot('UpperArm.R', -.48 * q, 0, -.18 * q) + rot('Forearm.R', -.38 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + for f in range(3): + rot('Finger%d.%s' % (f, side), -.45 * max(0, q)) + locs['Root'] = (0, -.02 * q, -.08 * q) + elif name == 'deposit': + # Lift the gathered spark into the back reservoir. + q = curve(t / dur, [(0, 0), (.30, .7), (.55, 1), (.80, .6), (1, 0)]) + rot('Spine', -.08 * q, -.25 * q, 0) + rot('Chest', -.05 * q, -.20 * q, 0) + rot('Head', -.10 * q, .15 * q, 0) + rot('UpperArm.R', -.70 * q, -.35 * q, -.25 * q) + rot('Forearm.R', -.90 * q) + rot('Hand.R', .40 * q) + rot('UpperArm.L', .15 * q, 0, .10 * q) + for f in range(3): + rot('Finger%d.R' % f, -.55 * max(0, q)) + locs['Root'] = (0, .01 * q, .02 * q) + elif name == 'return': + # Step back to the station and settle into the ready stance. + q = curve(t / dur, [(0, 0), (.40, 1), (1, 0)]) + rot('Spine', .06 * q, 0, -.04 * q) + rot('Thigh.L', -.18 * q) + rot('Thigh.R', .14 * q) + rot('Shin.L', .12 * q) + rot('Foot.L', -.10 * q) + rot('UpperArm.L', .10 * q) + rot('UpperArm.R', .08 * q) + rot('Head', .04 * q) + locs['Root'] = (0, .04 * q, 0) + elif name == 'hit': + q = curve(t, [(0, 0), (.07, 1), (.20, .45), (.42, 0)]) + rot('Spine', .14 * q, 0, -.08 * q) + rot('Head', .15 * q, 0, .06 * q) + rot('Forearm.L', -.12 * q) + rot('Forearm.R', -.10 * q) + elif name == 'death': + q = curve(t, [(0, 0), (.18, .08), (.65, .42), (1.20, 1), (1.50, .92), (1.9, 1)]) + rot('Root', -.85 * q, 0, .10 * q) + locs['Root'] = (0, -.12 * q, -.10 * q) + rot('Pelvis', -.18 * q) + rot('Spine', -.22 * q) + rot('Head', -.18 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('UpperArm.' + side, -.28 * q, 0, s * .14 * q) + rot('Forearm.' + side, -.40 * q) + rot('Thigh.' + side, .22 * q) + rot('Shin.' + side, -.38 * q) + for pb in rig.pose.bones: + pb.rotation_mode = 'QUATERNION' + r = rotations.get(pb.name, (0, 0, 0)) + q = Quaternion((0, 0, 1), r[2]) @ Quaternion((0, 1, 0), r[1]) @ Quaternion((1, 0, 0), r[0]) + basis = pb.bone.matrix_local.to_quaternion() + pb.rotation_quaternion = basis.inverted() @ q @ basis + pb.location = pb.bone.matrix_local.to_3x3().inverted() @ (Vector(locs.get(pb.name, (0, 0, 0))) * S) + +for name, (dur, loop) in clips.items(): + rig.animation_data_clear() + action = bpy.data.actions.new(name) + action.use_fake_user = True + rig.animation_data_create() + rig.animation_data.action = action + for frame in range(round(dur * 30) + 1): + animate(name, frame / 30, dur) + for pb in rig.pose.bones: + pb.keyframe_insert('rotation_quaternion', frame=frame) + pb.keyframe_insert('location', frame=frame) + action['loop'] = loop +rig.animation_data_clear() +rig.animation_data_create() +rig.animation_data.action = bpy.data.actions['idle'] +for pb in rig.pose.bones: + pb.rotation_quaternion = Quaternion() + pb.location = (0, 0, 0) +bpy.context.scene.render.fps = 30 +bpy.context.scene.frame_set(0) + +bpy.ops.wm.save_as_mainfile(filepath=str(SRC / 'arbeiter.blend')) +bpy.ops.file.make_paths_relative() +bpy.ops.wm.save_as_mainfile(filepath=str(SRC / 'arbeiter.blend')) +bpy.ops.object.select_all(action='DESELECT') +for ob in parts: + ob.select_set(True) +bpy.context.view_layer.objects.active = parts[0] +bpy.ops.object.join() +body = bpy.context.object +body.name = 'ArbeiterBody' +body.select_set(True) +rig.select_set(True) +bpy.context.view_layer.objects.active = rig +bpy.ops.export_scene.gltf( + filepath=str(OUT / 'arbeiter.glb'), + export_format='GLB', + use_selection=True, + export_animations=True, + export_animation_mode='ACTIONS', + export_force_sampling=True, + export_frame_range=False, + export_anim_slide_to_zero=True, + export_skins=True, + export_all_influences=False, + export_def_bones=True, + export_anim_single_armature=True, + export_materials='EXPORT', + export_yup=True, +) +raw = (OUT / 'arbeiter.glb').read_bytes() +import struct +doc = json.loads(raw[20:20 + struct.unpack_from(' 1.05 else 'Spine'], 8, 14) + leaf('BackLeaf_%d' % k, + (.18 * cos(a), .22, z + .18), + (.30 * cos(a), .12, z + .30), + .05, 'Chest' if z > 1.05 else 'Spine', 'leaf') +for j in range(24): + a = j * 1.7 + z = .5 + (j % 8) * .12 + ell('MossClump_%02d' % j, + (.12 * cos(a) * (1 + .05 * j), .08 * sin(a), z), + (.035, .028, .02), 'moss', 'Spine' if z < 1.0 else 'Chest', 8, 5) + +# Cleanup and skin +for ob in parts: + bm = bmesh.new() + bm.from_mesh(ob.data) + bmesh.ops.remove_doubles(bm, verts=list(bm.verts), dist=.0000005) + bmesh.ops.triangulate(bm, faces=list(bm.faces)) + bmesh.ops.dissolve_degenerate(bm, edges=list(bm.edges), dist=.0000001) + bmesh.ops.recalc_face_normals(bm, faces=list(bm.faces)) + if bm.calc_volume(signed=True) < 0: + bmesh.ops.reverse_faces(bm, faces=list(bm.faces)) + bm.to_mesh(ob.data) + bm.free() + ob.data.update() + +bpy.ops.object.armature_add(enter_editmode=True) +rig = bpy.context.object +rig.name = 'QuellRig' +ed = rig.data.edit_bones +ed.remove(ed[0]) +defs = {} + +def bone(name, head, tail, parent=None): + b = ed.new(name) + b.head = coord(head) + b.tail = coord(tail) + if parent: + b.parent = ed[parent] + defs[name] = (head, tail, parent) + +bone('Root', (0, 0, 0), (0, 0, .12)) +bone('Pelvis', (0, 0, .40), (0, 0, .75), 'Root') +bone('Spine', (0, 0, .75), (0, 0, 1.10), 'Pelvis') +bone('Chest', (0, 0, 1.10), (0, 0, 1.40), 'Spine') +bone('Head', (0, 0, 1.40), (0, 0, 1.75), 'Chest') +for s, side in [(-1, 'L'), (1, 'R')]: + bone('UpperArm.' + side, (s * .22, 0, 1.28), (s * .42, -.08, 1.10), 'Chest') + bone('Forearm.' + side, (s * .42, -.08, 1.10), (s * .55, -.18, .88), 'UpperArm.' + side) + bone('Hand.' + side, (s * .55, -.18, .88), (s * .58, -.28, .68), 'Forearm.' + side) + bone('Thigh.' + side, (s * .10, .04, .40), (s * .12, .02, .22), 'Pelvis') + bone('Shin.' + side, (s * .12, .02, .22), (s * .12, 0, .06), 'Thigh.' + side) + bone('Foot.' + side, (s * .12, 0, .06), (s * .12, -.12, .03), 'Shin.' + side) +bpy.ops.object.mode_set(mode='OBJECT') +for ob in parts: + mod = ob.modifiers.new('Weighted vine', 'ARMATURE') + mod.object = rig + ob.parent = rig + +clips = {'idle': (3.2, True), 'start': (.4, False), 'walk': (1.4, True), 'stop': (.4, False), + 'attack_a': (1.3, False), 'attack_b': (1.3, False), 'hit': (.48, False), 'ability': (1.9, False), 'death': (2.0, False)} + +def curve(t, keys): + for i in range(len(keys) - 1): + a, x = keys[i] + b, y = keys[i + 1] + if t <= b: + u = max(0, (t - a) / (b - a)) + u = u * u * (3 - 2 * u) + return x * (1 - u) + y * u + return keys[-1][1] + +def animate(name, t, dur): + rotations = {} + locs = {} + + def rot(b, x=0, y=0, z=0): + rotations[b] = (x, y, z) + + if name == 'idle': + q = sin(2 * pi * t / dur) + q2 = sin(2 * pi * t / dur * 2) + rot('Spine', .015 * q) + rot('Chest', -.02 * q, 0, .01 * q) + rot('Head', .025 * q, 0, -.012 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('Forearm.' + side, .03 * q, 0, s * .02 * q2) + locs['Root'] = (0, 0, .004 * q) + elif name in ('walk', 'start', 'stop'): + fade = 1 if name == 'walk' else sin(pi * .5 * t / dur) if name == 'start' else cos(pi * .5 * t / dur) + phase = t / 1.4 * 2 * pi + roll = sin(phase) * fade + rot('Pelvis', .01, 0, .04 * roll) + rot('Spine', -.03 * fade, 0, -.05 * roll) + rot('Chest', .02 * fade, 0, .03 * roll) + rot('Head', .04 * fade, 0, -.02 * roll) + for s, side in [(-1, 'L'), (1, 'R')]: + q = sin(phase + (0 if s < 0 else pi)) + lift = max(0, q) + rot('Thigh.' + side, .28 * q * fade) + rot('Shin.' + side, -.32 * lift * fade) + rot('Foot.' + side, (-.28 * q + .32 * lift) * fade) + rot('UpperArm.' + side, -.12 * q * fade, 0, s * .03 * fade) + rot('Forearm.' + side, -.15 * fade - .05 * lift, 0, s * .04 * fade) + locs['Root'] = (0, 0, (-.008 + .008 * cos(phase * 2)) * fade) + elif name == 'attack_a': + # Left tendril pulse, contact at 0.70 + q = curve(t / dur, [(0, 0), (.32, -.30), (.54, -.50), (.70, 1), (.82, .80), (1, 0)]) + rot('Spine', -.08 * q, .06 * q, .05 * q) + rot('Chest', -.06 * q, .05 * q, .08 * q) + rot('Head', .08 * q, 0, -.05 * q) + rot('UpperArm.L', -.85 * q, -.10 * q, .15 * q) + rot('Forearm.L', -.40 * q, 0, .10 * q) + rot('Hand.L', .25 * q) + rot('UpperArm.R', .12 * q) + elif name == 'attack_b': + q = curve(t / dur, [(0, 0), (.32, -.30), (.54, -.50), (.70, 1), (.82, .80), (1, 0)]) + rot('Spine', -.08 * q, -.06 * q, -.05 * q) + rot('Chest', -.06 * q, -.05 * q, -.08 * q) + rot('Head', .08 * q, 0, .05 * q) + rot('UpperArm.R', -.85 * q, .10 * q, -.15 * q) + rot('Forearm.R', -.40 * q, 0, -.10 * q) + rot('Hand.R', .25 * q) + rot('UpperArm.L', .12 * q) + elif name == 'hit': + q = curve(t, [(0, 0), (.08, 1), (.22, .5), (.48, 0)]) + rot('Spine', .12 * q, 0, -.07 * q) + rot('Head', .14 * q, 0, .05 * q) + rot('Forearm.L', -.12 * q) + rot('Forearm.R', -.10 * q) + elif name == 'ability': + # Multi-heal: arms open, core flares, leaves lift + q = curve(t / dur, [(0, 0), (.35, .7), (.70, 1), (1.3, .85), (1.9, 0)]) + rot('Spine', .10 * q) + rot('Chest', .08 * q) + rot('Head', -.18 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('UpperArm.' + side, -.35 * q, 0, s * .55 * q) + rot('Forearm.' + side, -.50 * q, 0, s * .25 * q) + rot('Hand.' + side, .20 * q) + locs['Root'] = (0, 0, .04 * q) + elif name == 'death': + q = curve(t, [(0, 0), (.2, .08), (.7, .45), (1.25, 1), (1.55, .90), (2.0, 1)]) + rot('Root', -.55 * q, 0, .08 * q) + locs['Root'] = (0, -.08 * q, -.08 * q) + rot('Spine', -.20 * q) + rot('Chest', -.15 * q) + rot('Head', -.25 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('UpperArm.' + side, -.40 * q, 0, s * .25 * q) + rot('Forearm.' + side, -.55 * q) + for pb in rig.pose.bones: + pb.rotation_mode = 'QUATERNION' + r = rotations.get(pb.name, (0, 0, 0)) + q = Quaternion((0, 0, 1), r[2]) @ Quaternion((0, 1, 0), r[1]) @ Quaternion((1, 0, 0), r[0]) + basis = pb.bone.matrix_local.to_quaternion() + pb.rotation_quaternion = basis.inverted() @ q @ basis + pb.location = pb.bone.matrix_local.to_3x3().inverted() @ (Vector(locs.get(pb.name, (0, 0, 0))) * S) + +for name, (dur, loop) in clips.items(): + rig.animation_data_clear() + action = bpy.data.actions.new(name) + action.use_fake_user = True + rig.animation_data_create() + rig.animation_data.action = action + for frame in range(round(dur * 30) + 1): + animate(name, frame / 30, dur) + for pb in rig.pose.bones: + pb.keyframe_insert('rotation_quaternion', frame=frame) + pb.keyframe_insert('location', frame=frame) + action['loop'] = loop +rig.animation_data_clear() +rig.animation_data_create() +rig.animation_data.action = bpy.data.actions['idle'] +for pb in rig.pose.bones: + pb.rotation_quaternion = Quaternion() + pb.location = (0, 0, 0) +bpy.context.scene.render.fps = 30 +bpy.context.scene.frame_set(0) + +bpy.ops.wm.save_as_mainfile(filepath=str(SRC / 'quellgeflecht.blend')) +bpy.ops.file.make_paths_relative() +bpy.ops.wm.save_as_mainfile(filepath=str(SRC / 'quellgeflecht.blend')) +bpy.ops.object.select_all(action='DESELECT') +for ob in parts: + ob.select_set(True) +bpy.context.view_layer.objects.active = parts[0] +bpy.ops.object.join() +body = bpy.context.object +body.name = 'QuellBody' +body.select_set(True) +rig.select_set(True) +bpy.context.view_layer.objects.active = rig +bpy.ops.export_scene.gltf( + filepath=str(OUT / 'quellgeflecht.glb'), + export_format='GLB', use_selection=True, + export_animations=True, export_animation_mode='ACTIONS', + export_force_sampling=True, export_frame_range=False, + export_anim_slide_to_zero=True, export_skins=True, + export_all_influences=False, export_def_bones=True, + export_anim_single_armature=True, export_materials='EXPORT', export_yup=True, +) +raw = (OUT / 'quellgeflecht.glb').read_bytes() +import struct +doc = json.loads(raw[20:20 + struct.unpack_from(' .5 else 28 + tex.inputs['Detail'].default_value = 2 + bump = n.new('ShaderNodeBump') + bump.inputs['Strength'].default_value = .12 if metal > .5 else .20 + bump.inputs['Distance'].default_value = .006 + links.new(tex.outputs['Fac'], bump.inputs['Height']) + links.new(bump.outputs['Normal'], bs.inputs['Normal']) + return m + + +# Concept: dark basalt chassis, brass frames, large orange crystal bow limbs. +M = { + 'basalt': material('Basalt', (.085, .085, .095), .80, 0), + 'plate': material('BasaltPlate', (.115, .11, .115), .70, .05), + 'bronze': material('Bronze', (.60, .42, .18), .34, .82), + 'edge': material('BronzeEdge', (.86, .64, .30), .26, .80), + 'joint': material('Joint', (.045, .045, .05), .58, .35), + 'iron': material('Iron', (.23, .24, .26), .38, .78), + 'crystal': material('Crystal', (1.0, .34, .05), .14, .05, .30), + 'ember': material('Ember', (1.0, .58, .14), .30, .10, 2.2), +} +CRYSTAL = ((.62, .12, .02), (1.0, .50, .10)) + + +def hash3(p, salt=0.): + v = sin(p[0] * 12.9898 + p[1] * 78.233 + p[2] * 37.719 + salt * 11.13) * 43758.5453 + return v - math.floor(v) + + +def mesh(name, vs, fs, kind, bone, weights=None, smooth=True, uv=None, facet=0., palette=None): + me = bpy.data.meshes.new(name) + me.from_pydata(vs, [], fs) + me.update() + ob = bpy.data.objects.new(name, me) + bpy.context.collection.objects.link(ob) + parts.append(ob) + me.materials.append(M[kind]) + col = me.color_attributes.new(name='SurfaceColor', type='FLOAT_COLOR', domain='CORNER') + tex = me.uv_layers.new(name='UVMap') + base = M[kind].diffuse_color[:3] + for face in me.polygons: + face.use_smooth = smooth + # Faceted crystal and rock: one tone per face, so facets read under a moving light. + h = hash3(face.center, len(parts)) if palette or facet else 0 + for li in face.loop_indices: + vi = me.loops[li].vertex_index + x, y, z = vs[vi] + if palette: + color = [a * (1 - h) + b * h for a, b in zip(*palette)] + elif facet: + color = [min(1, c * (1 - facet + 2 * facet * h)) for c in base] + else: + variation = .93 + .055 * sin(19 * x + 13 * z) + .025 * cos(22 * y - 9 * z) + color = [min(1, c * variation) for c in base] + col.data[li].color = (*color, 1) + tex.data[li].uv = uv[vi] if uv else (x * 1.7 + y * .3, z * 1.5) + groups = {} + for i in range(len(vs)): + ws = weights[i] if weights else {bone: 1.0} + total = sum(ws.values()) + for key, weight in ws.items(): + if weight <= 1e-8: + continue + groups.setdefault(key, ob.vertex_groups.get(key) or ob.vertex_groups.new(name=key)) + groups[key].add([i], weight / total, 'REPLACE') + return ob + + +def blend(a, b, t): + t = max(0, min(1, t)) + return {a: 1 - t, b: t} if a != b else {a: 1} + + +def smooth(u): + u = max(0, min(1, u)) + return u * u * (3 - 2 * u) + + +def catmull(points, t): + seg = min(len(points) - 2, int(t * (len(points) - 1))) + u = t * (len(points) - 1) - seg + a, b, c, d = [points[max(0, min(len(points) - 1, q))] for q in (seg - 1, seg, seg + 1, seg + 2)] + return .5 * ((2 * b) + (-a + c) * u + (2 * a - 5 * b + 4 * c - d) * u * u + (-a + 3 * b - 3 * c + d) * u * u * u) + + +def interp(values, t): + seg = min(len(values) - 2, int(t * (len(values) - 1))) + a = t * (len(values) - 1) - seg + return tuple(x * (1 - a) + y * a for x, y in zip(values[seg], values[seg + 1])) + + +def frame(tangent, hint): + t = tangent.normalized() + h = Vector(hint) + s = h - t * t.dot(h) + if s.length < 1e-5: + alt = Y if abs(t.y) < .9 else X + s = alt - t * t.dot(alt) + s.normalize() + return s, t.cross(s).normalized() + + +def chamfer(w, d, c=.3): + k = min(w, d) * c + return [(w, d - k), (w - k, d), (k - w, d), (-w, d - k), (-w, k - d), (k - w, -d), (w - k, -d), (w, k - d)] + + +def circle(sides): + return lambda w, d: [(w * cos(2 * pi * k / sides), d * sin(2 * pi * k / sides)) for k in range(sides)] + + +def lens(w, d): + # w: half height across the hint axis, d: half thickness. Six ridged crystal faces. + return [(w, 0), (w * .38, d), (-w * .38, d), (-w, 0), (-w * .38, -d), (w * .38, -d)] + + +def wedge(w, d): + return [(-w, -d), (w, -d), (0, d)] + + +def loft(name, path, sizes, kind, bone, hint=(1, 0, 0), profile=chamfer, steps=0, weight_fn=None, + smooth=False, facet=0., palette=None, jitter=0., tri=False): + """Closed prism along a path; profile axes are the hint direction and tangent x hint.""" + pts = [Vector(p) for p in path] + count = steps + 1 if steps else len(pts) + centers = [catmull(pts, j / (count - 1)) if steps else pts[j] for j in range(count)] + vs, fs, ws, uv = [], [], [], [] + n, length = 0, 0 + for j, c in enumerate(centers): + t = j / (count - 1) + s, u = frame(centers[min(count - 1, j + 1)] - centers[max(0, j - 1)], hint) + ring = profile(*interp(sizes, t)) + n = len(ring) + if j: + length += (c - centers[j - 1]).length + for k, (a, b) in enumerate(ring): + scale = 1 + jitter * (2 * hash3((j, k, len(parts))) - 1) if jitter and 0 < j < count - 1 else 1 + vs.append(c + (s * a + u * b) * scale) + ws.append(weight_fn(t) if weight_fn else {bone: 1}) + uv.append((k / n, length * 2)) + for j in range(1, count): + for k in range(n): + a, b = (j - 1) * n + k, (j - 1) * n + (k + 1) % n + if not tri: + fs.append((a, b, b + n, a + n)) + elif (j + k) % 2: + fs += [(a, b, a + n), (b, b + n, a + n)] + else: + fs += [(a, b, b + n), (a, b + n, a + n)] + fs += [tuple(reversed(range(n))), tuple(range((count - 1) * n, count * n))] + return mesh(name, vs, fs, kind, bone, ws, smooth, uv, facet, palette) + + +def tube(name, points, radii, kind, bone, sides=12, steps=16, weight_fn=None): + return loft(name, points, [(r, r) for r in radii], kind, bone, (0, 0, 1), circle(sides), + steps, weight_fn, smooth=True) + + +def strut(name, a, b, r, kind, bone, hint=(0, 0, 1)): + a, b = Vector(a), Vector(b) + # Overlap corners by less than the radius so neighbouring struts never share an edge. + d = (b - a).normalized() * r * .8 + return loft(name, [a - d, b + d], [(r, r), (r, r)], kind, bone, hint) + + +def disc(name, c, axis, r, width, kind, bone, sides=20): + c, ax = Vector(c), Vector(axis).normalized() + return loft(name, [c - ax * width / 2, c + ax * width / 2], [(r, r), (r, r)], kind, bone, + (0, 0, 1) if abs(ax.z) < .9 else (1, 0, 0), circle(sides)) + + +def annulus(name, c, axis, r_in, r_out, width, kind, bone, sides=20): + c, ax = Vector(c), Vector(axis).normalized() + s, u = frame(ax, (0, 0, 1) if abs(ax.z) < .9 else (1, 0, 0)) + vs, fs = [], [] + for r, off in ((r_out, -width / 2), (r_out, width / 2), (r_in, width / 2), (r_in, -width / 2)): + for k in range(sides): + a = 2 * pi * k / sides + vs.append(c + ax * off + (s * cos(a) + u * sin(a)) * r) + for ring in range(4): + nxt = (ring + 1) % 4 + for k in range(sides): + q = (k + 1) % sides + fs.append((ring * sides + k, ring * sides + q, nxt * sides + q, nxt * sides + k)) + return mesh(name, vs, fs, kind, bone, smooth=False) + + +def wheel(name, c, axis, r, width, spokes, kind, bone): + c, ax = Vector(c), Vector(axis).normalized() + s, u = frame(ax, (0, 0, 1)) + annulus(name + '_Rim', c, ax, r * .80, r, width, kind, bone, 24) + annulus(name + '_Lip', c + ax * width * .55, ax, r * .84, r * .96, width * .25, 'edge', bone, 24) + disc(name + '_Hub', c, ax, r * .30, width * 1.6, 'edge', bone, 12) + for k in range(spokes): + a = 2 * pi * (k + .5) / spokes + d = s * cos(a) + u * sin(a) + loft(name + '_Spoke%d' % k, [c + d * r * .24, c + d * r * .84], [(width * .30, r * .075)] * 2, + kind, bone, tuple(ax)) + for k in range(20): + a = 2 * pi * k / 20 + d = s * cos(a) + u * sin(a) + loft(name + '_Tooth%d' % k, [c + d * r * .96, c + d * r * 1.10], [(width * .42, r * .075), (width * .36, r * .05)], + kind, bone, tuple(ax)) + + +def rivet(name, c, normal, bone, r=.011): + return disc(name, c, normal, r, .012, 'edge', bone, 8) + + +def gem(name, c, up, side, top, bottom, r, kind, bone, sides=4, palette=CRYSTAL): + c, up = Vector(c), Vector(up).normalized() + s, u = frame(up, side) + vs = [c + up * top] + for k in range(sides): + a = 2 * pi * k / sides + vs.append(c + (s * cos(a) + u * sin(a)) * r) + vs.append(c - up * bottom) + fs = [] + for k in range(sides): + q = (k + 1) % sides + fs += [(0, 1 + k, 1 + q), (sides + 1, 1 + q, 1 + k)] + return mesh(name, vs, fs, kind, bone, smooth=False, palette=palette) + + +def on_segment(a, b, f, side_offset, front_offset, hint=(1, 0, 0)): + """Point on a limb segment, offset along the loft frame (hint side, tangent x hint front).""" + a, b = Vector(a), Vector(b) + s, u = frame(b - a, hint) + return a.lerp(b, f) + s * side_offset + u * front_offset + + +def ik_knee(a, c, l1, l2, pole): + delta = c - a + d = delta.length + if not abs(l1 - l2) + .00001 < d < l1 + l2 - .00001: + raise RuntimeError('Unreachable foot contact: %.6f for %.6f' % (d, l1 + l2)) + line = delta / d + v = Vector(pole) - a + perpendicular = (v - line * v.dot(line)).normalized() + along = (l1 * l1 - l2 * l2 + d * d) / (2 * d) + return a + line * along + perpendicular * sqrt(max(0, l1 * l1 - along * along)) + + +# ---------------------------------------------------------------- chassis (Pelvis) +loft('Hull', [(0, .24, .84), (0, .12, .84), (0, -.10, .84), (0, -.22, .84)], + [(.16, .11), (.20, .14), (.20, .14), (.15, .10)], 'basalt', 'Pelvis', facet=.10) +loft('Hull_Belt', [(0, .035, .84), (0, -.035, .84)], [(.212, .152)] * 2, 'bronze', 'Pelvis') +loft('Hull_Top_Plate', [(0, .19, .985), (0, -.17, .985)], [(.15, .022), (.14, .022)], 'plate', 'Pelvis', facet=.08) +loft('Hull_Nose', [(0, -.20, .84), (0, -.245, .835)], [(.13, .085), (.11, .07)], 'bronze', 'Pelvis') +loft('Hull_Keel', [(0, .12, .705), (0, -.14, .705)], [(.10, .035)] * 2, 'joint', 'Pelvis') +gem('Hull_Vent', (0, -.25, .82), (0, -1, 0), (1, 0, 0), .045, .01, .04, 'crystal', 'Pelvis', 4) +loft('Hull_Tail', [(0, .30, .86), (0, .23, .86)], [(.12, .075), (.14, .09)], 'bronze', 'Pelvis') +for s, side in [(-1, 'L'), (1, 'R')]: + hip = Vector((s * .24, .06, .80)) + disc('Hip_Housing_' + side, (s * .215, .06, .80), X, .115, .10, 'joint', 'Pelvis', 28) + annulus('Hip_Rim_' + side, (s * .268, .06, .80), X, .07, .12, .026, 'bronze', 'Pelvis', 32) + disc('Hip_Cap_' + side, (s * .284, .06, .80), X, .05, .03, 'edge', 'Pelvis', 12) + for k in range(6): + a = 2 * pi * k / 6 + disc('Hip_Bolt_%s%d' % (side, k), (s * .283, .06 + .095 * cos(a), .80 + .095 * sin(a)), X, + .011, .012, 'edge', 'Pelvis', 8) + loft('Hull_Side_Plate_' + side, [(s * .205, .17, .86), (s * .205, -.13, .86)], + [(.012, .085), (.012, .075)], 'plate', 'Pelvis', (1, 0, 0), facet=.08) + +# ---------------------------------------------------------------- turret neck (Spine) +disc('Turret_Ring', (0, .04, 1.00), Z, .15, .05, 'bronze', 'Spine', 32) +disc('Turret_Core', (0, .04, 1.06), Z, .115, .10, 'joint', 'Spine', 20) + +# ---------------------------------------------------------------- ballista (Weapon) +loft('Stock', [(0, .42, 1.17), (0, .20, 1.17), (0, -.40, 1.17), (0, -.66, 1.17)], + [(.085, .065), (.09, .07), (.085, .065), (.07, .055)], 'basalt', 'Weapon', facet=.10) +loft('Ember_Channel', [(0, .30, 1.245), (0, -.62, 1.245)], [(.03, .016)] * 2, 'ember', 'Weapon') +for s, side in [(-1, 'L'), (1, 'R')]: + loft('Rail_' + side, [(s * .058, .36, 1.25), (s * .058, -.64, 1.25)], [(.016, .018)] * 2, 'edge', 'Weapon') +for k, y in enumerate((-.52, -.16, .14)): + loft('Stock_Band_%d' % k, [(0, y + .03, 1.17), (0, y - .03, 1.17)], [(.098, .078)] * 2, 'bronze', 'Weapon') + for s in (-1, 1): + for z in (1.14, 1.20): + rivet('Band_Rivet_%d_%d_%d' % (k, s, round(z * 100)), (s * .099, y, z), X, 'Weapon') +for s in (-1, 1): + for z in (1.12, 1.28): + rivet('Rear_Rivet_%d_%d' % (s, round(z * 100)), (s * .08, .576, z), Y, 'Weapon') + for z in (.79, .89): + rivet('Belt_Rivet_%d_%d' % (s, round(z * 100)), (s * .213, 0, z), X, 'Pelvis') +loft('Muzzle', [(0, -.64, 1.17), (0, -.72, 1.17)], [(.08, .062), (.074, .056)], 'bronze', 'Weapon') +annulus('Muzzle_Ring', (0, -.725, 1.20), Y, .026, .05, .02, 'edge', 'Weapon', 16) +loft('Bow_Mount', [(0, -.24, 1.16), (0, -.38, 1.16)], [(.17, .06), (.16, .055)], 'bronze', 'Weapon') +loft('Bow_Mount_Core', [(0, -.235, 1.16), (0, -.385, 1.16)], [(.12, .045)] * 2, 'joint', 'Weapon') +loft('Trigger_Box', [(0, .20, 1.07), (0, -.04, 1.07)], [(.07, .05)] * 2, 'joint', 'Weapon') +loft('Rear_Housing', [(0, .54, 1.20), (0, .28, 1.20)], [(.16, .15), (.15, .14)], 'basalt', 'Weapon', facet=.10) +loft('Rear_Top_Plate', [(0, .55, 1.36), (0, .27, 1.36)], [(.15, .018)] * 2, 'bronze', 'Weapon') +loft('Rear_Fin', [(0, .50, 1.395), (0, .34, 1.395)], [(.10, .04), (.06, .04)], 'bronze', 'Weapon', (1, 0, 0), wedge) +loft('Rear_Back_Plate', [(0, .555, 1.20), (0, .575, 1.20)], [(.11, .10)] * 2, 'plate', 'Weapon') +gem('Rear_Sight', (0, .58, 1.26), (0, 1, 0), (1, 0, 0), .035, .005, .03, 'crystal', 'Weapon', 4) +for s, side in [(-1, 'L'), (1, 'R')]: + x = s * .167 + corners = [(x, .30, 1.08), (x, .52, 1.08), (x, .52, 1.32), (x, .30, 1.32)] + for k in range(4): + strut('Truss_%s%d' % (side, k), corners[k], corners[(k + 1) % 4], .013, 'bronze', 'Weapon', (1, 0, 0)) + strut('Truss_Diagonal_' + side, (x, .30, 1.08), (x, .52, 1.32), .012, 'bronze', 'Weapon', (1, 0, 0)) + disc('Truss_Rivet_' + side, (x, .41, 1.20), X, .022, .02, 'edge', 'Weapon', 10) + +# Crank wheels on both stock sides share one Gear bone (reload winds them). +GEAR = Vector((0, -.02, 1.17)) +disc('Gear_Axle', GEAR, X, .026, .27, 'iron', 'Gear', 12) +for s, side in [(-1, 'L'), (1, 'R')]: + wheel('Crank_Wheel_' + side, GEAR + X * s * .118, X, .13, .03, 5, 'bronze', 'Gear') + +# Bow limbs: faceted crystal, cocked backwards; each bends gradually from root to tip. +LIMB = [(.14, -.31, 1.165), (.35, -.38, 1.172), (.60, -.33, 1.176), (.80, -.16, 1.168), (.89, .03, 1.155)] + + +def limb_point(s, t): + return catmull([Vector((s * p[0], p[1], p[2])) for p in LIMB], t) + + +for s, side in [(-1, 'L'), (1, 'R')]: + limb, tip = 'Limb.' + side, 'LimbTip.' + side + + def limb_weights(t, limb=limb, tip=tip): + return blend(limb, tip, (t - .16) / .66) + + path = [(s * p[0], p[1], p[2]) for p in LIMB] + loft('Crystal_Limb_' + side, path, [(.092, .046), (.086, .042), (.070, .034), (.050, .025), (.028, .013)], + 'crystal', limb, (0, 0, 1), lens, 18, limb_weights, palette=CRYSTAL, jitter=.045, tri=True) + loft('Limb_Clamp_' + side, [limb_point(s, 0), limb_point(s, .11)], [(.10, .054), (.095, .05)], + 'bronze', limb, (0, 0, 1)) + loft('Limb_Clamp_Edge_' + side, [limb_point(s, .105), limb_point(s, .13)], [(.104, .058)] * 2, + 'edge', limb, (0, 0, 1)) + loft('Limb_Band_' + side, [limb_point(s, .30), limb_point(s, .345)], [(.086, .044)] * 2, + 'bronze', limb, (0, 0, 1)) + loft('Limb_Tip_Cap_' + side, [limb_point(s, .87), limb_point(s, 1.0) + Vector((s * .012, .03, 0))], + [(.046, .030), (.040, .026)], 'bronze', tip, (0, 0, 1)) + disc('Limb_Tip_Eye_' + side, limb_point(s, 1.0) + Vector((0, .035, 0)), Z, .024, .07, 'edge', tip, 10) + + def cable_weights(t, tip=tip): + return blend(tip, 'Draw', (t - .05) / .90) + + tube('Draw_Cable_' + side, [limb_point(s, 1.0) + Vector((0, .035, .002)), (s * .012, .262, 1.286)], + [.0085, .0085], 'iron', tip, 8, 18, cable_weights) + +loft('Nock_Claw', [(0, .31, 1.286), (0, .225, 1.286)], [(.036, .03), (.03, .026)], 'bronze', 'Draw') +for s in (-1, 1): + loft('Nock_Prong_%d' % s, [(s * .022, .235, 1.30), (s * .022, .205, 1.31)], [(.008, .008)] * 2, 'edge', 'Draw') + +# Bolt (Bolt) with a long crystal quarrel head (Quarrel). +loft('Bolt_Shaft', [(0, .25, 1.29), (0, -.70, 1.29)], [(.017, .017)] * 2, 'iron', 'Bolt') +for s in (-1, 1): + loft('Bolt_Vane_%d' % s, [(s * .03, .22, 1.29), (s * .03, .08, 1.29)], [(.02, .004), (.012, .004)], 'edge', 'Bolt') +loft('Bolt_Vane_Top', [(0, .22, 1.322), (0, .08, 1.322)], [(.004, .018), (.004, .011)], 'edge', 'Bolt') +disc('Quarrel_Collar', (0, -.69, 1.29), Y, .028, .03, 'edge', 'Quarrel', 10) +loft('Quarrel_Head', [(0, -.685, 1.29), (0, -.75, 1.29), (0, -.87, 1.29), (0, -1.0, 1.29)], + [(.022, .022), (.056, .056), (.040, .040), (.004, .004)], 'crystal', 'Quarrel', (0, 0, 1), circle(6), + palette=CRYSTAL, jitter=.06, tri=True) + +# ---------------------------------------------------------------- legs +LEGS = {} +for s, side in [(-1, 'L'), (1, 'R')]: + H = Vector((s * .24, .06, .80)) + K = Vector((s * .27, -.12, .47)) + A = Vector((s * .28, .10, .17)) + B = Vector((s * .28, -.03, .05)) + T = Vector((s * .28, -.21, .02)) + LEGS[side] = {'H': H, 'K': K, 'A': A, 'B': B, 'T': T, + 'pole': K + (K - (H + A) / 2).normalized() * .6} + thigh, shin, tarsus, foot = 'Thigh.' + side, 'Shin.' + side, 'Tarsus.' + side, 'Foot.' + side + # Rigid armor over continuous flexible sleeves at hip, knee, ankle and toe joints. + loft('Thigh_Armor_' + side, [H.lerp(K, .10), H.lerp(K, .50), H.lerp(K, .90)], + [(.075, .09), (.092, .115), (.07, .085)], 'basalt', thigh, facet=.10) + loft('Thigh_Trim_' + side, [on_segment(H, K, f, s * .078, .094) for f in (.16, .5, .84)], + [(.018, .016)] * 3, 'edge', thigh) + loft('Thigh_Plate_' + side, [on_segment(H, K, f, s * .092, 0) for f in (.2, .5, .8)], + [(.012, .075), (.012, .09), (.012, .065)], 'plate', thigh, facet=.08) + gem('Thigh_Crystal_' + side, on_segment(H, K, .64, 0, .105), K - H, (1, 0, 0), .085, .055, .048, 'crystal', thigh) + disc('Knee_Joint_' + side, K, X, .085, .20, 'joint', shin, 28) + annulus('Knee_Rim_' + side, K + X * s * .102, X, .045, .092, .03, 'bronze', shin, 32) + disc('Knee_Cap_' + side, K + X * s * .118, X, .042, .026, 'edge', shin, 12) + loft('Shin_Armor_' + side, [K.lerp(A, .12), K.lerp(A, .50), K.lerp(A, .88)], + [(.07, .08), (.082, .10), (.062, .07)], 'basalt', shin, facet=.10) + loft('Shin_Band_' + side, [K.lerp(A, .76), K.lerp(A, .86)], [(.078, .082)] * 2, 'bronze', shin) + loft('Shin_Plate_' + side, [on_segment(K, A, f, s * .082, 0) for f in (.2, .45, .7)], + [(.012, .06), (.012, .08), (.012, .06)], 'plate', shin, facet=.08) + gem('Shin_Crystal_' + side, on_segment(K, A, .38, 0, .09), A - K, (1, 0, 0), .07, .05, .04, 'crystal', shin) + disc('Ankle_Joint_' + side, A, X, .065, .16, 'joint', tarsus, 24) + annulus('Ankle_Rim_' + side, A + X * s * .082, X, .034, .07, .026, 'bronze', tarsus, 28) + loft('Tarsus_Armor_' + side, [A.lerp(B, .12), A.lerp(B, .88)], [(.058, .055), (.052, .048)], + 'basalt', tarsus, facet=.10) + loft('Spur_' + side, [A + Vector((0, .03, -.05)), Vector((s * .28, .20, .02))], [(.03, .028), (.010, .009)], + 'joint', tarsus, facet=.10) + loft('Spur_Cap_' + side, [Vector((s * .28, .175, .026)), Vector((s * .28, .215, .013))], + [(.022, .02), (.006, .005)], 'edge', tarsus) + loft('Foot_Base_' + side, [B + Vector((0, .05, 0)), B + Vector((0, -.05, -.005))], [(.085, .045), (.08, .04)], + 'basalt', foot, facet=.10) + loft('Foot_Band_' + side, [B + Vector((0, .012, .002)), B + Vector((0, -.012, .001))], [(.09, .05)] * 2, + 'bronze', foot) + for k in (-1, 0, 1): + root = Vector((B.x + k * .052, B.y - .03, .038)) + tip = Vector((B.x + k * .078, B.y - .19 + .025 * abs(k), .014)) + loft('Toe_%s%d' % (side, k + 1), [root, root.lerp(tip, .5) + Vector((0, 0, .006)), tip], + [(.029, .030), (.025, .023), (.012, .008)], 'joint', foot, facet=.10) + loft('Toe_Claw_%s%d' % (side, k + 1), [tip.lerp(root, .30), tip + Vector((k * .004, -.028, -.004))], + [(.026, .018), (.006, .004)], 'edge', foot) + + def sleeve(parent, child, a, b): + return lambda t: blend(parent, child, (t - a) / (b - a)) + + for f in (.28, .72): + for off in (-.045, .045): + rivet('Thigh_Rivet_%s_%d_%d' % (side, f * 100, off * 1000), on_segment(H, K, f, s * .105, off), X, thigh, .009) + for off in (-.035, .035): + rivet('Shin_Rivet_%s_%d' % (side, off * 1000), on_segment(K, A, .45, s * .095, off), X, shin, .008) + hose_a = [Vector((s * .17, .21, .79)), Vector((s * .21, .20, .70)), on_segment(H, K, .42, s * .02, -.105)] + tube('Hip_Hose_' + side, hose_a, [.017, .018, .017], 'joint', 'Pelvis', 10, 22, sleeve('Pelvis', thigh, .25, .80)) + disc('Hip_Hose_Ferrule_' + side, hose_a[0], hose_a[0] - hose_a[1], .024, .03, 'bronze', 'Pelvis', 10) + disc('Hip_Hose_Clamp_' + side, hose_a[2], K - H, .023, .03, 'bronze', thigh, 10) + hose_b = [on_segment(H, K, .70, s * .03, -.092), K + Vector((s * .03, .09, .01)), on_segment(K, A, .34, s * .03, -.082)] + tube('Knee_Hose_' + side, hose_b, [.015, .016, .015], 'joint', thigh, 10, 22, sleeve(thigh, shin, .30, .70)) + disc('Knee_Hose_Clamp_T_' + side, hose_b[0], K - H, .021, .026, 'bronze', thigh, 10) + disc('Knee_Hose_Clamp_S_' + side, hose_b[2], A - K, .021, .026, 'bronze', shin, 10) + + tube('Hip_Sleeve_' + side, [Vector((s * .15, .06, .86)), H, H.lerp(K, .24)], [.064, .062, .058], + 'joint', 'Pelvis', 14, 18, sleeve('Pelvis', thigh, .30, .78)) + tube('Knee_Sleeve_' + side, [H.lerp(K, .70), K, K.lerp(A, .30)], [.056, .06, .052], + 'joint', thigh, 14, 18, sleeve(thigh, shin, .28, .72)) + tube('Ankle_Sleeve_' + side, [K.lerp(A, .74), A, A.lerp(B, .36)], [.046, .05, .044], + 'joint', shin, 12, 16, sleeve(shin, tarsus, .28, .72)) + tube('Toe_Sleeve_' + side, [A.lerp(B, .66), B, B + Vector((0, -.05, -.004))], [.036, .038, .034], + 'joint', tarsus, 12, 14, sleeve(tarsus, foot, .30, .70)) + +# Recalculate coherent outward normals and export triangulated closed surfaces. +for ob in parts: + bm = bmesh.new() + bm.from_mesh(ob.data) + bmesh.ops.remove_doubles(bm, verts=list(bm.verts), dist=.0000001) + bmesh.ops.triangulate(bm, faces=list(bm.faces)) + bmesh.ops.recalc_face_normals(bm, faces=list(bm.faces)) + if bm.calc_volume(signed=True) < 0: + bmesh.ops.reverse_faces(bm, faces=list(bm.faces)) + bm.to_mesh(ob.data) + bm.free() + ob.data.update() + +bpy.ops.object.armature_add(enter_editmode=True) +rig = bpy.context.object +rig.name = 'GlassRig' +ed = rig.data.edit_bones +ed.remove(ed[0]) + + +def bone(name, head, tail, parent=None): + b = ed.new(name) + b.head = head + b.tail = tail + if parent: + b.parent = ed[parent] + defs[name] = (Vector(head), Vector(tail), parent) + + +bone('Root', (0, 0, 0), (0, 0, .15)) +bone('Pelvis', (0, .06, .80), (0, .06, .98), 'Root') +bone('Spine', (0, .04, .98), (0, .04, 1.10), 'Pelvis') +bone('Weapon', (0, .02, 1.17), (0, -.60, 1.17), 'Spine') +bone('Gear', GEAR, GEAR + Vector((.12, 0, 0)), 'Weapon') +bone('Draw', (0, .262, 1.286), (0, .36, 1.286), 'Weapon') +bone('Bolt', (0, .25, 1.29), (0, -.685, 1.29), 'Weapon') +bone('Quarrel', (0, -.685, 1.29), (0, -1.0, 1.29), 'Bolt') +for s, side in [(-1, 'L'), (1, 'R')]: + bone('Limb.' + side, limb_point(s, 0), limb_point(s, .5), 'Weapon') + bone('LimbTip.' + side, limb_point(s, .5), limb_point(s, 1.0), 'Limb.' + side) + leg = LEGS[side] + bone('Thigh.' + side, leg['H'], leg['K'], 'Pelvis') + bone('Shin.' + side, leg['K'], leg['A'], 'Thigh.' + side) + bone('Tarsus.' + side, leg['A'], leg['B'], 'Shin.' + side) + bone('Foot.' + side, leg['B'], leg['T'], 'Tarsus.' + side) +bpy.ops.object.mode_set(mode='OBJECT') +for ob in parts: + mod = ob.modifiers.new('Weighted ballista deformation', 'ARMATURE') + mod.object = rig + ob.parent = rig +rig.show_in_front = True + +clips = {'idle': (3.0, True), 'start': (.4, False), 'walk': (1.2, True), 'stop': (.4, False), + 'attack_a': (1.3, False), 'attack_b': (1.3, False), 'hit': (.5, False), + 'ability': (1.3, False), 'death': (2.0, False)} +WALK, STRIDE, DUTY = 1.2, .52, .6 +STANCE = STRIDE * DUTY # planted foot travels backwards with the body's 0.52 m per cycle +L1 = {side: (LEGS[side]['K'] - LEGS[side]['H']).length for side in LEGS} +L2 = {side: (LEGS[side]['A'] - LEGS[side]['K']).length for side in LEGS} + + +def curve(t, keys): + for (a, x), (b, y) in zip(keys, keys[1:]): + if t <= b: + u = max(0, (t - a) / (b - a)) + u = u * u * (3 - 2 * u) + return x * (1 - u) + y * u + return keys[-1][1] + + +def pose_rotation(pb, r): + q = Quaternion((0, 0, 1), r[2]) @ Quaternion((0, 1, 0), r[1]) @ Quaternion((1, 0, 0), r[0]) + basis = pb.bone.matrix_local.to_quaternion() + return basis.inverted() @ q @ basis + + +def aim_bone(name, head, tail): + pb = rig.pose.bones[name] + rest = pb.bone.matrix_local + direction = defs[name][1] - defs[name][0] + rotation = direction.rotation_difference(tail - head).to_matrix().to_4x4() + pose = rotation @ rest + pose.translation = head + pb.matrix = pose + bpy.context.view_layer.update() + + +def foot_plan(tau, offset, amp): + """Ball offset along Y, lift, heel raise and toe droop for one foot at walk time tau.""" + u = (tau / WALK + offset) % 1.0 + if u < DUTY: + w = u / DUTY + return STANCE * (w - .5) * amp, 0, .42 * smooth((w - .72) / .28) * amp, 0, True + w = (u - DUTY) / (1 - DUTY) + return (STANCE * (.5 - smooth(w)) * amp, .10 * sin(pi * w) * amp, + .42 * (1 - smooth(w / .45)) * amp, .28 * sin(pi * w) * amp, False) + + +def place_leg(side, dy, lift, heel, toe): + leg = LEGS[side] + ball = leg['B'] + Vector((0, dy, lift)) + ankle = ball + Quaternion(X, heel) @ (leg['A'] - leg['B']) + toes = ball + Quaternion(X, toe) @ (leg['T'] - leg['B']) + hip = rig.pose.bones['Thigh.' + side].head.copy() + pelvis = rig.pose.bones['Pelvis'].matrix @ rig.data.bones['Pelvis'].matrix_local.inverted() + knee = ik_knee(hip, ankle, L1[side], L2[side], pelvis @ leg['pole']) + aim_bone('Thigh.' + side, hip, knee) + aim_bone('Shin.' + side, knee, ankle) + aim_bone('Tarsus.' + side, ankle, ball) + aim_bone('Foot.' + side, ball, toes) + foot = rig.pose.bones['Foot.' + side] + return max((foot.head - ball).length, (foot.tail - toes).length, + (rig.pose.bones['Shin.' + side].tail - ankle).length), foot.head.copy(), foot.tail.copy() + + +def animate(name, t, dur): + rs, locs, scales = {}, {}, {} + legs = {'L': (0, 0, 0, 0, True), 'R': (0, 0, 0, 0, True)} + + def rot(b, x=0, y=0, z=0): + rs[b] = (x, y, z) + + if name == 'idle': + ph = 2 * pi * t / dur + breath = sin(ph) + locs['Pelvis'] = (0, 0, -.006 + .006 * cos(ph)) + rot('Pelvis', .006 * breath) + rot('Spine', 0, 0, .045 * sin(ph + .4)) + rot('Weapon', -.012 - .008 * breath) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('Limb.' + side, 0, 0, s * .006 * breath) + rot('LimbTip.' + side, 0, 0, s * .008 * breath) + elif name in ('walk', 'start', 'stop'): + amp = 1 if name == 'walk' else smooth(t / dur) if name == 'start' else 1 - smooth(t / dur) + ph = 2 * pi * t / WALK + roll = -.03 * sin(ph) * amp + yaw = .025 * sin(ph) * amp + locs['Pelvis'] = (0, 0, -.024 * (.5 + .5 * cos(2 * pi * (t - .07) / (WALK / 2))) * amp) + rot('Pelvis', .03 * amp, roll, yaw) + # The turret counters the gait so the bolt stays on target. + rot('Spine', -.024 * amp, -.8 * roll, -.9 * yaw) + rot('Weapon', -.012 + .01 * sin(2 * ph) * amp) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('LimbTip.' + side, 0, 0, s * .02 * sin(2 * ph - 1.0) * amp) + legs = {'L': foot_plan(t, 0, amp), 'R': foot_plan(t, .5, amp)} + elif name in ('attack_a', 'attack_b', 'ability'): + braced = name == 'attack_b' + charged = name == 'ability' + aim = curve(t, [(0, 0), (.30, .8), (.60, 1), (.90, 1), (1.04, .8), (1.30, 0)]) + release = curve(t, [(0, 0), (.90, 0), (.933333, 1), (.98, 1), (1.24, 0), (1.30, 0)]) + recoil = curve(t, [(0, 0), (.90, 0), (.933333, 1), (1.04, .22), (1.14, 0), (1.30, 0)]) + charge = curve(t, [(0, 0), (.15, 0), (.85, 1), (.90, 1), (.92, 0), (1.30, 0)]) if charged else 0 + k = 1.45 if charged else .75 if braced else 1.0 + crouch = (.10 if charged else .07 if braced else .018) * aim + locs['Pelvis'] = (0, .045 * recoil * k, -crouch) + rot('Pelvis', -.05 * recoil * k + (.02 * aim if braced else 0)) + rot('Spine', 0, 0, .04 * sin(pi * min(1, t / .9)) * aim if braced else 0) + rot('Weapon', (.012 if braced else -.035) * aim - .09 * recoil * k - .02 * charge) + wobble = .05 * sin(38 * (t - .933333)) * exp(-9 * (t - .933333)) if t > .933333 else 0 + for s, side in [(-1, 'L'), (1, 'R')]: + # Limbs spring forward on release, then the crank draws them back to cocked. + rot('Limb.' + side, 0, 0, s * (-.10 * release + .05 * charge)) + rot('LimbTip.' + side, 0, 0, s * (-.16 * release + .06 * charge + wobble)) + locs['Draw'] = (0, -.34 * release + .05 * charge, 0) + if t < .90: + bolt, size = 0, 1 + elif t < .95: + u = (t - .90) / .05 + bolt, size = -1.2 * u * u, 1 - .999 * smooth(u) + elif t < 1.02: + bolt, size = -1.2, .001 + else: + u = smooth((t - 1.02) / .22) + bolt, size = .30 * (1 - u), max(.001, u) + locs['Bolt'] = (0, bolt, 0) + scales['Bolt'] = size + wind = -2 * pi * smooth((t - .96) / .28) + if charged: + wind -= 2 * pi * smooth((t - .12) / .73) + spin = smooth((t - .15) / .75) + rot('Quarrel', 0, 4 * pi * spin, 0) + scales['Quarrel'] = 1 + .22 * charge * (.6 + .4 * sin(26 * t)) + rot('Gear', wind) + elif name == 'hit': + q = curve(t, [(0, 0), (.066667, 1), (.20, .4), (.5, 0)]) + wob = sin(30 * t) * exp(-7 * t) + locs['Pelvis'] = (0, .035 * q, -.015 * q) + rot('Pelvis', -.04 * q, .05 * q, 0) + rot('Spine', .05 * q, 0, -.07 * q) + rot('Weapon', -.06 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('LimbTip.' + side, 0, 0, s * .05 * wob) + elif name == 'death': + q = curve(t, [(0, 0), (.3, .12), (.72, .58), (1.25, 1), (1.5, .96), (2, 1)]) + stagger = curve(t, [(0, 0), (.18, 1), (.5, .25), (.8, 0)]) + snap = curve(t, [(0, 0), (.24, 0), (.30, 1), (2, 1)]) + locs['Pelvis'] = (0, .05 * stagger - .04 * q, -.33 * q) + rot('Pelvis', .20 * q - .05 * stagger, -.12 * q, .08 * q) + rot('Spine', .06 * q, 0, -.10 * q) + rot('Weapon', .16 * q) + rot('Gear', -.8 * q) + # Destroyed: the bow tension lets go and the limbs sag. + locs['Draw'] = (0, -.30 * snap, -.02 * q) + locs['Bolt'] = (0, -.06 * q, -.005 * q) + for s, side in [(-1, 'L'), (1, 'R')]: + rot('Limb.' + side, 0, s * .06 * q, -s * .09 * snap) + rot('LimbTip.' + side, 0, s * .22 * q, -s * .14 * snap + s * .05 * q) + for pb in rig.pose.bones: + pb.rotation_mode = 'QUATERNION' + pb.rotation_quaternion = pose_rotation(pb, rs.get(pb.name, (0, 0, 0))) + pb.location = pb.bone.matrix_local.to_3x3().inverted() @ Vector(locs.get(pb.name, (0, 0, 0))) + size = scales.get(pb.name, 1.0) + pb.scale = (size, size, size) + bpy.context.view_layer.update() + errors = [] + for side in ('L', 'R'): + dy, lift, heel, toe, planted = legs[side] + error, ball, toes = place_leg(side, dy, lift, heel, toe) + errors.append(error) + foot_samples.append({'clip': name, 't': t, 'side': side, 'planted': planted and lift == 0, + 'ball': tuple(ball), 'toe': tuple(toes)}) + contact_samples.append({'clip': name, 't': round(t, 6), 'max_leg_error': max(errors)}) + + +for name, (dur, loop) in clips.items(): + rig.animation_data_clear() + rig.animation_data_create() + action = bpy.data.actions.new(name) + action.use_fake_user = True + rig.animation_data.action = action + for frame in range(round(dur * 30) + 1): + animate(name, frame / 30, dur) + for pb in rig.pose.bones: + pb.keyframe_insert('rotation_quaternion', frame=frame) + pb.keyframe_insert('location', frame=frame) + pb.keyframe_insert('scale', frame=frame) + action['loop'] = loop + action['contact_seconds'] = .90 if name in ('attack_a', 'attack_b', 'ability') else -1 + for layer in action.layers: + for strip in layer.strips: + for bag in strip.channelbags: + for fc in bag.fcurves: + for key in fc.keyframe_points: + key.interpolation = 'LINEAR' +rig.animation_data_clear() +rig.animation_data_create() +rig.animation_data.action = bpy.data.actions['idle'] +bpy.context.scene.render.fps = 30 +bpy.context.scene.frame_set(0) + +bpy.ops.wm.save_as_mainfile(filepath=str(SRC / 'glasballiste.blend')) +source_parts = len(parts) +bpy.ops.object.select_all(action='DESELECT') +for ob in parts: + ob.select_set(True) +bpy.context.view_layer.objects.active = parts[0] +bpy.ops.object.join() +body = bpy.context.object +body.name = 'GlassBody' +body.select_set(True) +rig.select_set(True) +bpy.context.view_layer.objects.active = rig +bpy.ops.export_scene.gltf(filepath=str(OUT / 'glasballiste.glb'), export_format='GLB', use_selection=True, + export_animations=True, export_animation_mode='ACTIONS', export_force_sampling=True, + export_frame_range=False, export_anim_slide_to_zero=True, export_skins=True, + export_all_influences=False, export_def_bones=True, export_anim_single_armature=True, + export_materials='EXPORT', export_yup=True) +raw = (OUT / 'glasballiste.glb').read_bytes() +doc = json.loads(raw[20:20 + struct.unpack_from(' + +Saumwacht · Assetgalerie · Phase 3 + + +

Saumwacht / Werkstatt / Phase 03

+

Die Welt nimmt Form an.

Einheiten, Ressourcen und Oberflächen in einer gemeinsamen Bildsprache. Native PNG-Originale vergleichen, Details prüfen und Prompts nachlesen.

+
Geplant
66
Vorhanden
66
Ausstehend
0
+
+ + + +
+
Hintergrund zur Alpha-Prüfung
+
Icongröße
+

Karten und UI behalten ihr Seitenverhältnis. Ein Klick aufs Bild öffnet das Original.

+ +

66 Assets · 66 vorhanden · 0 ausstehend

+ +
+

Offline-Galerie · Bilder unverändert aus den nativen PNG-Masters.

Aktualisieren: python3 tools/build_asset_gallery.py

+ diff --git a/assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png b/assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png new file mode 100644 index 0000000..b0f85bb Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png b/assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png new file mode 100644 index 0000000..69f3bc1 Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png b/assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png new file mode 100644 index 0000000..a41e00e Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png b/assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png new file mode 100644 index 0000000..7dfee3d Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png b/assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png new file mode 100644 index 0000000..e5d87e1 Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png b/assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png new file mode 100644 index 0000000..7f4b3b4 Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png b/assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png new file mode 100644 index 0000000..828595f Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png b/assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png new file mode 100644 index 0000000..7b5e73f Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png b/assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png new file mode 100644 index 0000000..ac257a4 Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png differ diff --git a/assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png b/assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png new file mode 100644 index 0000000..4db8000 Binary files /dev/null and b/assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png differ diff --git a/assets-source/phase3/masters/map/map_lane_edge.png b/assets-source/phase3/masters/map/map_lane_edge.png new file mode 100644 index 0000000..fb951f9 Binary files /dev/null and b/assets-source/phase3/masters/map/map_lane_edge.png differ diff --git a/assets-source/phase3/masters/map/map_lane_floor.png b/assets-source/phase3/masters/map/map_lane_floor.png new file mode 100644 index 0000000..d4a3ead Binary files /dev/null and b/assets-source/phase3/masters/map/map_lane_floor.png differ diff --git a/assets-source/phase3/masters/map/map_leak_line.png b/assets-source/phase3/masters/map/map_leak_line.png new file mode 100644 index 0000000..6442a2b Binary files /dev/null and b/assets-source/phase3/masters/map/map_leak_line.png differ diff --git a/assets-source/phase3/masters/map/map_overview.png b/assets-source/phase3/masters/map/map_overview.png new file mode 100644 index 0000000..37bfaf2 Binary files /dev/null and b/assets-source/phase3/masters/map/map_overview.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png b/assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png new file mode 100644 index 0000000..9459b3b Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png b/assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png new file mode 100644 index 0000000..6de38b7 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png b/assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png new file mode 100644 index 0000000..be168bf Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png b/assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png new file mode 100644 index 0000000..293f052 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png b/assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png new file mode 100644 index 0000000..060ff44 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png b/assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png new file mode 100644 index 0000000..3abcbf8 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png b/assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png new file mode 100644 index 0000000..be3b233 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png b/assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png new file mode 100644 index 0000000..cb1ea81 Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png b/assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png new file mode 100644 index 0000000..0e00b3e Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png differ diff --git a/assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png b/assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png new file mode 100644 index 0000000..64fb66f Binary files /dev/null and b/assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png differ diff --git a/assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png b/assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png new file mode 100644 index 0000000..b8c8357 Binary files /dev/null and b/assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png differ diff --git a/assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png b/assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png new file mode 100644 index 0000000..adc8041 Binary files /dev/null and b/assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png differ diff --git a/assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png b/assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png new file mode 100644 index 0000000..5e02cc4 Binary files /dev/null and b/assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png differ diff --git a/assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png b/assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png new file mode 100644 index 0000000..91a98b2 Binary files /dev/null and b/assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png differ diff --git a/assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png b/assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png new file mode 100644 index 0000000..77c1cd1 Binary files /dev/null and b/assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png differ diff --git a/assets-source/phase3/masters/neutral/worker_funkenleser_icon.png b/assets-source/phase3/masters/neutral/worker_funkenleser_icon.png new file mode 100644 index 0000000..c2e9bef Binary files /dev/null and b/assets-source/phase3/masters/neutral/worker_funkenleser_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png new file mode 100644 index 0000000..668ae1d Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png new file mode 100644 index 0000000..8168dc1 Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png new file mode 100644 index 0000000..c46d585 Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png new file mode 100644 index 0000000..9e935c5 Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png new file mode 100644 index 0000000..8cb7217 Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png new file mode 100644 index 0000000..538f76d Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png new file mode 100644 index 0000000..8c6e080 Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png new file mode 100644 index 0000000..87f639f Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png new file mode 100644 index 0000000..6e8fc4b Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png differ diff --git a/assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png b/assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png new file mode 100644 index 0000000..bed770e Binary files /dev/null and b/assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png differ diff --git a/assets-source/phase3/masters/resources/res_core.png b/assets-source/phase3/masters/resources/res_core.png new file mode 100644 index 0000000..4cf62f3 Binary files /dev/null and b/assets-source/phase3/masters/resources/res_core.png differ diff --git a/assets-source/phase3/masters/resources/res_gold.png b/assets-source/phase3/masters/resources/res_gold.png new file mode 100644 index 0000000..db6508a Binary files /dev/null and b/assets-source/phase3/masters/resources/res_gold.png differ diff --git a/assets-source/phase3/masters/resources/res_income.png b/assets-source/phase3/masters/resources/res_income.png new file mode 100644 index 0000000..64f29bd Binary files /dev/null and b/assets-source/phase3/masters/resources/res_income.png differ diff --git a/assets-source/phase3/masters/resources/res_sparks.png b/assets-source/phase3/masters/resources/res_sparks.png new file mode 100644 index 0000000..5876c1a Binary files /dev/null and b/assets-source/phase3/masters/resources/res_sparks.png differ diff --git a/assets-source/phase3/masters/types/type_armor_aether.png b/assets-source/phase3/masters/types/type_armor_aether.png new file mode 100644 index 0000000..8b24732 Binary files /dev/null and b/assets-source/phase3/masters/types/type_armor_aether.png differ diff --git a/assets-source/phase3/masters/types/type_armor_heavy.png b/assets-source/phase3/masters/types/type_armor_heavy.png new file mode 100644 index 0000000..fcc9438 Binary files /dev/null and b/assets-source/phase3/masters/types/type_armor_heavy.png differ diff --git a/assets-source/phase3/masters/types/type_armor_light.png b/assets-source/phase3/masters/types/type_armor_light.png new file mode 100644 index 0000000..1b69deb Binary files /dev/null and b/assets-source/phase3/masters/types/type_armor_light.png differ diff --git a/assets-source/phase3/masters/types/type_damage_blade.png b/assets-source/phase3/masters/types/type_damage_blade.png new file mode 100644 index 0000000..cfe6bdc Binary files /dev/null and b/assets-source/phase3/masters/types/type_damage_blade.png differ diff --git a/assets-source/phase3/masters/types/type_damage_pierce.png b/assets-source/phase3/masters/types/type_damage_pierce.png new file mode 100644 index 0000000..670d053 Binary files /dev/null and b/assets-source/phase3/masters/types/type_damage_pierce.png differ diff --git a/assets-source/phase3/masters/types/type_damage_pulse.png b/assets-source/phase3/masters/types/type_damage_pulse.png new file mode 100644 index 0000000..63e38a4 Binary files /dev/null and b/assets-source/phase3/masters/types/type_damage_pulse.png differ diff --git a/assets-source/phase3/masters/ui/ui_button_disabled.png b/assets-source/phase3/masters/ui/ui_button_disabled.png new file mode 100644 index 0000000..538b520 Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_button_disabled.png differ diff --git a/assets-source/phase3/masters/ui/ui_button_hover.png b/assets-source/phase3/masters/ui/ui_button_hover.png new file mode 100644 index 0000000..43f512b Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_button_hover.png differ diff --git a/assets-source/phase3/masters/ui/ui_button_normal.png b/assets-source/phase3/masters/ui/ui_button_normal.png new file mode 100644 index 0000000..62d34d4 Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_button_normal.png differ diff --git a/assets-source/phase3/masters/ui/ui_button_pressed.png b/assets-source/phase3/masters/ui/ui_button_pressed.png new file mode 100644 index 0000000..05622c3 Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_button_pressed.png differ diff --git a/assets-source/phase3/masters/ui/ui_panel_a.png b/assets-source/phase3/masters/ui/ui_panel_a.png new file mode 100644 index 0000000..f807540 Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_panel_a.png differ diff --git a/assets-source/phase3/masters/ui/ui_panel_b.png b/assets-source/phase3/masters/ui/ui_panel_b.png new file mode 100644 index 0000000..cc1fd41 Binary files /dev/null and b/assets-source/phase3/masters/ui/ui_panel_b.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png new file mode 100644 index 0000000..8eea237 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png new file mode 100644 index 0000000..9cbf36a Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png new file mode 100644 index 0000000..647b0ee Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png new file mode 100644 index 0000000..59ac090 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png new file mode 100644 index 0000000..7a99188 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png new file mode 100644 index 0000000..9f47670 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png new file mode 100644 index 0000000..f3efa19 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png new file mode 100644 index 0000000..6553736 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png new file mode 100644 index 0000000..1668a25 Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png differ diff --git a/assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png b/assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png new file mode 100644 index 0000000..99dafdc Binary files /dev/null and b/assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png differ diff --git a/assets-source/phase3/qa-icons.html b/assets-source/phase3/qa-icons.html new file mode 100644 index 0000000..fc8cdc0 --- /dev/null +++ b/assets-source/phase3/qa-icons.html @@ -0,0 +1 @@ +Saumwacht · 48px Sichtprüfung

Saumwacht · 56 Icons bei 48 Pixeln

Native PNGs, Browseranzeige 48 × 48 · dunkel / hell · Zur Assetgalerie

g01 · Kohlenbeißer

g02 · Schlackenklaue

g03 · Schlackenwacht

g04 · Basaltbastion

g05 · Funkenlanze

g06 · Glasballiste

g07 · Aschenwerfer

g08 · Kraterrufer

g09 · Herdhüter

g10 · Sonnenesse

m01 · Kesselwicht

m02 · Druckhüter

m03 · Scherschreiter

m04 · Sechsklingler

m05 · Bolzenknecht

m06 · Linienmeister

m07 · Klangkolben

m08 · Resonanzramme

m09 · Taktspindel

m10 · Taktprälat

n01 · Saummaske

n02 · Grenzmaske

n03 · Fadentänzer

n04 · Saumzertrenner

n05 · Fernflüsterer

n06 · Fernrufer

n07 · Glockenschlepper

n08 · Hohlgeläut

n09 · Maskenkantor

n10 · Vielstimmenkantor

w01 · Dornhopser

w02 · Rankenschnapper

w03 · Korkrücken

w04 · Ringborke

w05 · Samenschleuder

w06 · Zapfenkrone

w07 · Sporenkelch

w08 · Pilzkathedrale

w09 · Tauhüter

w10 · Quellgeflecht

s01 · Nadelspäher

s02 · Rostschieber

s03 · Dunstsänger

s04 · Keilbrecher

s05 · Risszehrer

res_gold · Gold

res_sparks · Funken

res_income · Einkommen

res_core · Kernleben

worker_funkenleser · Funkenleser

type_damage_blade · Klinge

type_damage_pierce · Durchschlag

type_damage_pulse · Impuls

type_armor_light · Leichte Rüstung

type_armor_heavy · Schwere Rüstung

type_armor_aether · Ätherische Rüstung

\ No newline at end of file diff --git a/assets-source/phase3/records/g01.json b/assets-source/phase3/records/g01.json new file mode 100644 index 0000000..855e0db --- /dev/null +++ b/assets-source/phase3/records/g01.json @@ -0,0 +1,12 @@ +{ + "id": "g01", + "display_name": "Kohlenbeißer", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Kompakter Basaltkörper mit glühendem Maul, kräftigen Klauen und Messingakzenten.", + "prompt": "Use case: stylized-concept. Create ONE standalone square transparent-background game unit icon for an original low-poly fantasy tower-defense autobattler called Saumwacht. Asset ID g01, Kohlenbeißer. Subject: a squat living coal creature, charcoal-black angular boulder body, broad glowing ember mouth, two powerful short clawed arms and sturdy small legs. Simple memorable triangular silhouette, no humanoid human face. Faction Glutpakt palette exactly basalt #292B35, ember orange #EF6B3B, restrained brass #D9A441 and ash #D8CEC0. Style: flat illustrated strategy-game UI icon, crisp confident edges, 3 to 4 broad matte color values per material, subtle graphic shading, NO photorealistic or glossy rendered look. Entire single character centered, 3/4 front view facing slightly right, slight overhead angle, soft neutral key light upper left. Art occupies about 78% of canvas, broad transparent safety margin around all sides, no elements clipped. Readable at 48px. True RGBA transparent background; no checkerboard baked into image, no colored rectangle, no ground, no shadow on background, no badge, no frame, no text, no lettering, no watermark. Intended final icon 256x256 pixels, square master if higher resolution is required. Save useful image output; one character only.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-38fac772-ec12-4d2b-8925-e70601932eaa.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g02.json b/assets-source/phase3/records/g02.json new file mode 100644 index 0000000..2ae55e2 --- /dev/null +++ b/assets-source/phase3/records/g02.json @@ -0,0 +1,12 @@ +{ + "id": "g02", + "display_name": "Schlackenklaue", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Schwer gepanzerter Kohlenkörper mit breiten Basaltschultern, glühendem Maul und großen messingbesetzten Klauen.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: Upgraded coal-claw melee creature: heavy angular basalt shoulder plates, two oversized curved brass-tipped claws, broad ember-filled jagged mouth, glowing cracks, compact powerful legs. Visibly a heavier evolved coal creature; not a human.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-c9760a9f-f0e9-4f5d-8884-e6488c8ef2cc.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g03.json b/assets-source/phase3/records/g03.json new file mode 100644 index 0000000..09c1687 --- /dev/null +++ b/assets-source/phase3/records/g03.json @@ -0,0 +1,12 @@ +{ + "id": "g03", + "display_name": "Schlackenwacht", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Gedrungener Basaltwächter mit breiter Schildfront, schmaler Ofenglut und kurzen, kräftigen Armen.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: A defensive living basalt sentinel. Broad squat rectangular slab-shaped body forming a huge shield front, small recessed orange furnace slit, two short armored arms with blocklike fists, sturdy feet. Strong nearly square silhouette, restrained brass edge accents; clearly a tank rather than a clawed monster.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-72c5994e-0c7a-4143-8818-51d35141938c.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g04.json b/assets-source/phase3/records/g04.json new file mode 100644 index 0000000..6423cb9 --- /dev/null +++ b/assets-source/phase3/records/g04.json @@ -0,0 +1,12 @@ +{ + "id": "g04", + "display_name": "Basaltbastion", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Lebende Basaltfestung mit gestuften Schultern, gepanzerter Schildfront und glühendem Ofenkern.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: Upgraded living fortress tank, massive broad stepped basalt slabs forming a castle-like shoulder silhouette, deep orange furnace slit, a thick angular tower-shield chest and two pillar-like arms, robust feet, controlled brass buttresses. Distinct from a plain block sentinel: layered fortress tiers, wider shoulders, taller crown of stone, still one compact creature.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-b8f50103-9bf6-4218-8525-aead4d3e51cb.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g05.json b/assets-source/phase3/records/g05.json new file mode 100644 index 0000000..6667003 --- /dev/null +++ b/assets-source/phase3/records/g05.json @@ -0,0 +1,12 @@ +{ + "id": "g05", + "display_name": "Funkenlanze", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Schlanker Glutkonstrukt-Schütze mit langer Messinglanze und orange leuchtender Glasspitze.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: A slender mobile ember construct with narrow charcoal stone torso, two sturdy legs, a single long brass-and-obsidian lance launcher held diagonally forward, a pointed glowing orange glass spearhead, small angular head without a human face. Clearly a light ranged marksman with an elongated weapon silhouette, not a knight with a shield.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-060575d4-bb01-4f8b-a30e-563a72cc22b2.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g06.json b/assets-source/phase3/records/g06.json new file mode 100644 index 0000000..b83671c --- /dev/null +++ b/assets-source/phase3/records/g06.json @@ -0,0 +1,12 @@ +{ + "id": "g06", + "display_name": "Glasballiste", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Bewegliche Glasballiste mit großen orangefarbenen Kristallarmen, langem Bolzen und stabilem Basaltunterbau.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: An upgraded mobile glass ballista creature, a compact charcoal basalt construct on two sturdy articulated legs supporting a very large crossbow with two swept crystalline orange limbs, long glowing glass bolt, brass mechanical bands. Three-quarter angle, bow fits entirely inside square; clearly a heavy ranged siege unit and evolved spear launcher, no shield.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-3b6b580d-dda5-4aba-92eb-5c33ef578b57.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g07.json b/assets-source/phase3/records/g07.json new file mode 100644 index 0000000..0334b93 --- /dev/null +++ b/assets-source/phase3/records/g07.json @@ -0,0 +1,12 @@ +{ + "id": "g07", + "display_name": "Aschenwerfer", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Gedrungener Aschenwerfer mit breitem Mörserkelch, glühender Kohle und kurzen Basaltbeinen.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: A squat mobile ash mortar creature, charcoal faceted stone body and two short arms cradling a wide upward-tilted round basalt mortar bowl. One contained orange ember glowing inside the bowl, tiny restrained ash puff attached to opening. Stubby legs, brass rim, broad cup silhouette; original artillery creature rather than a human soldier.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-fe9d03d4-bdc3-438b-9083-c15f881de061.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g08.json b/assets-source/phase3/records/g08.json new file mode 100644 index 0000000..71b2a1d --- /dev/null +++ b/assets-source/phase3/records/g08.json @@ -0,0 +1,12 @@ +{ + "id": "g08", + "display_name": "Kraterrufer", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Schwerer Kraterkörper mit großem Vulkankelch, glühendem Inneren und gestuften Basaltplatten.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: Heavy evolved ash-mortar creature: broad armored basalt body with a very large crater-shaped mortar bowl in its shoulders, layered brass-rimmed volcanic plates, contained orange molten core, one small angular ash curl, two massive arms and stout legs. Strong wide circular crater silhouette, clearly the upgraded artillery of a smaller bowl creature, no scenery.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-ca06a766-1878-4c6d-aa15-1c8d21280ec2.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g09.json b/assets-source/phase3/records/g09.json new file mode 100644 index 0000000..b5237db --- /dev/null +++ b/assets-source/phase3/records/g09.json @@ -0,0 +1,12 @@ +{ + "id": "g09", + "display_name": "Herdhüter", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Kleiner Herdwächter mit offenem Glutofen und einer schützenden Messingschale vor dem Körper.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Intended icon 256px with a high-resolution square master. Subject: Small gentle living hearth guardian, upright compact basalt furnace body on short legs, open orange hearth at chest, two small arms holding a modest warm brass brazier before the body. Rounded arch opening, ash-colored upper stone hood, a few restrained ember shapes. Support unit with protective welcoming silhouette, no human face, no weapons.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-9dc97472-ad0e-41ae-9e22-dd2ad50d284a.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/g10.json b/assets-source/phase3/records/g10.json new file mode 100644 index 0000000..ea94127 --- /dev/null +++ b/assets-source/phase3/records/g10.json @@ -0,0 +1,12 @@ +{ + "id": "g10", + "display_name": "Sonnenesse", + "faction": "glutpakt", + "kind": "unit_icon", + "description_de": "Große Sonnenesse mit strahlender Ofenöffnung, Messingkrone und breiter wärmender Glutschale.", + "prompt": "Use case: stylized-concept. ONE standalone square unit icon for the original strategy game Saumwacht. Whole single creature centered with all limbs visible, about 76% canvas coverage and transparent margins. Three-quarter front view facing slightly right, slight overhead angle, soft neutral key light upper left. Faceted illustrated game UI art with crisp edges, broad matte planes, restrained graphic shading, very clear silhouette readable at 48px. True RGBA transparent background, no checkerboard, no ground, no shadow on background, no border, no badge, no text, no watermark. Glutpakt palette basalt #292B35, ember #EF6B3B, brass #D9A441, ash #D8CEC0. Large simple shapes, no tiny surface texture, no glossy photorealism. Subject: Grand evolved living solar forge support creature: broad upright basalt furnace body, large radiant orange sunlike forge opening framed by a simple brass sun crown, ash stone mantle, sturdy feet, arms holding a wide healing ember basin. Warm controlled gold-orange illumination, majestic open silhouette; clearly stronger than small hearth guardian, still one creature without scenic halo background.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-78c6d895-0631-491f-956a-28a74e7e9049.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m01.json b/assets-source/phase3/records/m01.json new file mode 100644 index 0000000..b366e36 --- /dev/null +++ b/assets-source/phase3/records/m01.json @@ -0,0 +1,12 @@ +{ + "id": "m01", + "display_name": "Kesselwicht", + "description_de": "Gedrungener Kesseltank mit rundem Petrolkessel, Keramikgesicht und kurzen Stempelbeinen.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: a squat friendly formidable boiler tank automaton, round low petrol boiler body, small cream ceramic face inset into the upper front, ocher pressure gauge, short thick piston legs, two low blocky steel fists, one short chimney; simple round compact silhouette.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-c138bf79-c48f-4dc6-aff3-0968e159757a.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m02.json b/assets-source/phase3/records/m02.json new file mode 100644 index 0000000..3a0009a --- /dev/null +++ b/assets-source/phase3/records/m02.json @@ -0,0 +1,12 @@ +{ + "id": "m02", + "display_name": "Druckhüter", + "description_de": "Breiter gepanzerter Drucktank mit Schulterkesseln und massivem Schildarm.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: an upgraded massive armored pressure tank automaton, very broad squared shoulders supporting two tall ocher-capped pressure cylinders, cream ceramic brow above steel face, thick petrol chest armor, massive block shield forearm and heavy piston fist, sturdy short legs; trapezoid broad powerful silhouette distinct from the small round boiler base unit.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-5b0544b5-1d30-495c-b66a-2945478ecde8.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m03.json b/assets-source/phase3/records/m03.json new file mode 100644 index 0000000..167d872 --- /dev/null +++ b/assets-source/phase3/records/m03.json @@ -0,0 +1,12 @@ +{ + "id": "m03", + "display_name": "Scherschreiter", + "description_de": "Schmaler Schreitautomat mit zwei großen Scherenarmen.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: a nimble walking twin-shear automaton with a narrow upright petrol spindle body, two very large open steel scissors replacing its arms, each with two clearly defined long blade halves, jointed ocher knees and long light legs, a small pointed cream ceramic head; light angular insect-like silhouette with exactly two shear arms.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-2ce66046-595f-4163-8996-ff00d8aa83d1.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m04.json b/assets-source/phase3/records/m04.json new file mode 100644 index 0000000..27c8a7c --- /dev/null +++ b/assets-source/phase3/records/m04.json @@ -0,0 +1,12 @@ +{ + "id": "m04", + "display_name": "Sechsklingler", + "description_de": "Breiter Schreitautomat mit sechs deutlich getrennten Klingen.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: an upgraded six-bladed walking automaton, broad petrol hub torso with a cream ceramic mask, exactly six large steel swordlike blades on six distinct jointed arms fanning out three per side, ocher hubs, tall strong jointed legs; dramatic radial blade silhouette distinctly larger and more elaborate than a two-shear machine.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-d02ba6ad-4b15-4157-a093-c6ac7593c037.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m05.json b/assets-source/phase3/records/m05.json new file mode 100644 index 0000000..2175648 --- /dev/null +++ b/assets-source/phase3/records/m05.json @@ -0,0 +1,12 @@ +{ + "id": "m05", + "display_name": "Bolzenknecht", + "description_de": "Schlanker Bolzenautomat mit einem deutlich lesbaren Armwerfer.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: a slim bolt-launcher automaton, narrow petrol body on two slender steel legs, small cream ceramic face and ocher monocular sight, one large compact crossbow bolter replacing the right forearm and a small bolt magazine on its back, simple upright posture; one strongly readable crossbow weapon and restrained silhouette.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-f587da38-e177-4167-8f3b-d2848ee3a991.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m06.json b/assets-source/phase3/records/m06.json new file mode 100644 index 0000000..9e7f717 --- /dev/null +++ b/assets-source/phase3/records/m06.json @@ -0,0 +1,12 @@ +{ + "id": "m06", + "display_name": "Linienmeister", + "description_de": "Hoher Präzisionsautomat mit einer langen integrierten Balliste.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: an upgraded tall precision ballista automaton, long petrol armored torso, cream ceramic pointed visor with ocher targeting lens, a long oversize precision ballista integrated across its upper torso with broad steel bow limbs and a long forward rail, stabilizer heel struts and a thin vertical targeting mast; tall triangular precision silhouette distinctly larger than a slim bolt-launcher.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-f5bde69e-3ed6-4c2a-a716-9ccade0d64ca.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m07.json b/assets-source/phase3/records/m07.json new file mode 100644 index 0000000..dcf8c18 --- /dev/null +++ b/assets-source/phase3/records/m07.json @@ -0,0 +1,12 @@ +{ + "id": "m07", + "display_name": "Klangkolben", + "description_de": "Kompakter Artillerieautomat mit einem großen Glockenrohr und Kolben.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: a compact piston-bell artillery automaton on two stout mechanical feet, one large ocher bell-shaped acoustic cannon angled slightly upward to the right, petrol barrel body, thick central steel striking piston visible at bell mouth, cream ceramic inset on the side, small short operator head; single horizontal bell silhouette.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-305c0b2d-78b6-44b5-9521-e2d12a900c7e.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m08.json b/assets-source/phase3/records/m08.json new file mode 100644 index 0000000..3f682eb --- /dev/null +++ b/assets-source/phase3/records/m08.json @@ -0,0 +1,12 @@ +{ + "id": "m08", + "display_name": "Resonanzramme", + "description_de": "Breiter Artillerieautomat mit zwei großen Resonanzkesseln.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: an upgraded broad resonance-ram artillery automaton, two enormous side-by-side forward-facing ocher resonance drums, dark steel piston centers and petrol mounting armor, small cream ceramic central command mask between the drums, four chunky steel stabilizer legs; extremely wide twin-circle silhouette distinctly different from a single small bell cannon.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-c602457d-3e07-4ab0-b5f0-20603487de64.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m09.json b/assets-source/phase3/records/m09.json new file mode 100644 index 0000000..70bcde5 --- /dev/null +++ b/assets-source/phase3/records/m09.json @@ -0,0 +1,12 @@ +{ + "id": "m09", + "display_name": "Taktspindel", + "description_de": "Kleiner Taktgeber auf Spindelbeinen mit einem Dirigentenstab.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: a small elegant clockwork conductor automaton, slim upright petrol spindle body widening at the middle, tiny cream ceramic face, ocher pendulum inset in the chest, two thin steel legs and narrow articulated arms, holding a single small ocher conductor baton raised diagonally; simple graceful spindle silhouette.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-7c9e483a-fd8f-4d40-af51-b18052b6ceeb.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/m10.json b/assets-source/phase3/records/m10.json new file mode 100644 index 0000000..63753ec --- /dev/null +++ b/assets-source/phase3/records/m10.json @@ -0,0 +1,12 @@ +{ + "id": "m10", + "display_name": "Taktprälat", + "description_de": "Großer Uhrwerkdirigent mit kronenförmigem Metronom und breitem Mantelkörper.", + "prompt": "Use case: stylized-concept. Asset type: original strategy-game UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy machine, strong chunky planar shapes and simple matte shading, premium coherent game icon, not photorealistic. Composition: square 1:1 canvas, whole single subject centered, all parts visible with comfortable transparent margin, occupy about 75–80 percent of the canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key light from upper left, restrained ambient fill. Palette: petrol #247A80 primary, ocher #C79A48 accents, steel #657481, cream ceramic #E6DCCA; dark slate shadows. Keep broad masses and silhouette readable at 48px. Scene: genuinely transparent background with preserved alpha, no checkerboard pattern drawn into image. No ground, no shadow plane, no frame, no text, no lettering, no logo, no border, no watermark, no unrelated props, no other characters, no realistic texture or excessive microdetail. Subject: an upgraded grand clockwork conductor automaton, tall imposing petrol bell-shaped ceremonial mantle made of broad mechanical armor plates, cream ceramic mask, large ocher metronome crown with three clearly readable prongs, visible ocher pendulum in its torso, two steel articulated arms conducting with a long baton, small sturdy feet; regal wide triangular silhouette distinctly different from the small thin spindle conductor.", + "faction": "nietenkonvent", + "kind": "unit_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-4af73e05-9b9a-4456-b743-cc89d9c3b138.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/map_lane_edge.json b/assets-source/phase3/records/map_lane_edge.json new file mode 100644 index 0000000..3ba7d1e --- /dev/null +++ b/assets-source/phase3/records/map_lane_edge.json @@ -0,0 +1,12 @@ +{ + "id": "map_lane_edge", + "display_name": "Lane-Randkachel", + "faction": "map", + "kind": "tile_concept", + "description_de": "Passende Randplatte mit niedriger äußerer Steinbrüstung und kleinem Messingmarker.", + "prompt": "Original SAUMWACHT fantasy strategy terrain concept art. Matte hand-painted low-poly facets, broad simple polygonal planes, weathered grey stone #657481 and basalt #292B35, moss green #56845A, restrained brass #D9A441. Soft directional illumination from upper left. Orthographic oblique overhead view with camera looking down 55 degrees, no perspective convergence. Calm readable surfaces, no units, characters, text, letters, labels, legend, watermark, UI panels, logos or borrowed game designs. One isolated square modular lane-edge terrain tile representing a 2m by 2m grey stone slab, shallow 20cm base thickness. Full diamond-shaped oblique square with side faces visible. Flat unobstructed build-floor top with a low straight 30cm retaining stone curb along ONLY the far/right edge; a narrow brass marker is inset into the middle of this curb. Other three edges flat and modular. Tiny moss clumps tucked beneath the outside of the curb. No railing around whole tile, no buildings, no glyphs, no crystal. Tile centered with ample margin on a flat desaturated blue-grey backdrop; subtle small contact shadow. Entire tile visible, single tile only.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-16c351f6-4a68-4146-8c0c-fe9bb0f6dd83.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/map/map_lane_edge.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/map_lane_floor.json b/assets-source/phase3/records/map_lane_floor.json new file mode 100644 index 0000000..85c4352 --- /dev/null +++ b/assets-source/phase3/records/map_lane_floor.json @@ -0,0 +1,12 @@ +{ + "id": "map_lane_floor", + "display_name": "Baufeld-Bodenkachel", + "faction": "map", + "kind": "tile_concept", + "description_de": "Flache quadratische Steinplatte mit großen ruhigen Flächen und schmalen Moosfugen für das Baufeld.", + "prompt": "Original SAUMWACHT fantasy strategy terrain concept art. Matte hand-painted low-poly facets, broad simple polygonal planes, weathered grey stone #657481 and basalt #292B35, moss green #56845A, restrained brass #D9A441. Soft directional illumination from upper left. Orthographic oblique overhead view with camera looking down 55 degrees, no perspective convergence. Calm readable surfaces, no units, characters, text, letters, labels, legend, watermark, UI panels, logos or borrowed game designs. One isolated square modular build-floor terrain tile representing a 2m by 2m square stone slab, shallow 20cm thickness, shown as a full diamond-shaped oblique square with both side faces visible. Four broad grey slate planes across a flat completely unobstructed top, very thin cracks and tiny moss seams near the outside edges only. No raised objects, no parapet, no crystal, no emblem. All four outer edges straight and modular. Tile centered with ample margin on a flat desaturated blue-grey backdrop; subtle small contact shadow. Entire tile clearly visible. Single tile only, no sheet or multiple views.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-0fca82f6-36dc-477c-a226-482fd1acea62.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/map/map_lane_floor.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/map_leak_line.json b/assets-source/phase3/records/map_leak_line.json new file mode 100644 index 0000000..d9908d4 --- /dev/null +++ b/assets-source/phase3/records/map_leak_line.json @@ -0,0 +1,12 @@ +{ + "id": "map_leak_line", + "display_name": "Lecklinie-Kachel", + "faction": "map", + "kind": "tile_concept", + "description_de": "Steinplatte mit durchgehendem mintfarbenem Lichtstreifen in einer schmalen Messingschiene als Lecklinie.", + "prompt": "Original SAUMWACHT fantasy strategy terrain concept art. Matte hand-painted low-poly facets, broad simple polygonal planes, weathered grey stone #657481 and basalt #292B35, moss green #56845A, restrained brass #D9A441. Soft directional illumination from upper left. Orthographic oblique overhead view with camera looking down 55 degrees, no perspective convergence. Calm readable surfaces, no units, characters, text, letters, labels, legend, watermark, UI panels, logos or borrowed game designs. One isolated square modular leak-line terrain tile representing a 2m by 2m grey stone slab, shallow 20cm thickness. Full diamond-shaped oblique square with side faces visible. Flat stone top crossed from the midpoint of its left edge to the midpoint of its right edge by one thin continuous mint glowing strip #82DBCE inside a narrow flat brass inlay, perfectly flush with the floor, meant to connect into a straight line across adjacent tiles. Keep most top surface plain stone. No raised obstacles, no arrows, no letters, no symbols. Centered with ample margin on a flat desaturated blue-grey backdrop, subtle small contact shadow. Entire tile visible, single tile only.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-d7b0bd9b-1ba6-4cf7-a787-60b1564fdf62.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/map/map_leak_line.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/map_overview.json b/assets-source/phase3/records/map_overview.json new file mode 100644 index 0000000..7ad37ec --- /dev/null +++ b/assets-source/phase3/records/map_overview.json @@ -0,0 +1,12 @@ +{ + "id": "map_overview", + "display_name": "Doppelsteg – Kartenkonzept", + "faction": "map", + "kind": "map_concept", + "description_de": "Zwei parallele Felsstege über einer Schlucht, mit nördlichen Aufmarschflächen, mittleren Baufeldern und südlichen Kernplattformen in Türkis und Koralle.", + "prompt": "Original SAUMWACHT fantasy strategy terrain concept art. Matte hand-painted low-poly facets, broad simple polygonal planes, weathered grey stone #657481 and basalt #292B35, moss green #56845A, restrained brass #D9A441. Soft directional illumination from upper left. Orthographic oblique overhead view with camera looking down 55 degrees, no perspective convergence. Calm readable surfaces, no units, characters, text, letters, labels, legend, watermark, UI panels, logos or borrowed game designs. Create a wide landscape overview of one entire small symmetrical two-lane battlefield named Doppelsteg. Two separate long rectangular floating rock terraces running vertically north at top to south at bottom, parallel, with a narrow deep mist-filled chasm between. Both lanes equally wide and equally long; approximate width to length ratio 12:40 for each lane. Each lane consists from north/top to south/bottom of an open spawn apron, a central flat build field subdivided into subtle square stone pavers, a short plain approach, and a small southern raised core dais. Left core is a compact glowing mint crystal #82DBCE held in a brass cradle; right core a coral crystal #E9967C. A thin matching colored brass-inlaid leak stripe crosses each lane directly before its core. Keep the middle build fields empty and clear, stone edges only at outer borders, small tufts of moss confined to borders. No bridges crossing the gap and no extra lanes. Entire two-terrace silhouette visible with margin on all sides. Dark blue-grey mist and distant plain background, restrained atmospheric depth. This is environment art reference, no infographic.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-ab60fe13-bb3f-4999-b130-f7e9864f15c9.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/map/map_overview.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n01.json b/assets-source/phase3/records/n01.json new file mode 100644 index 0000000..7b81342 --- /dev/null +++ b/assets-source/phase3/records/n01.json @@ -0,0 +1,12 @@ +{ + "id": "n01", + "display_name": "Saummaske", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Kompakter gefalteter Nebelkörper mit heller Ovalmaske, Sichelarmen und zwei Standranken.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy game unit icon, square transparent PNG. Subject: SAUMMASKE, a small defensive nonhuman mist spirit made of folded indigo and violet mist planes, standing on two short folded tendril feet. One large free-standing smooth oval pale mist mask with two narrow mint eye slits, a compact oval shield-like front body and small crescent arms. Its silhouette is compact, simple and beginner-tier. No human face, no human wizard, no hood. Style: polished faceted illustrated strategy-game icon, broad matte low-poly-like faces, very few large clean shapes, readable at 48px. Composition: entire single creature centered, occupies 75-80 percent of a square canvas, ample transparent margin on all sides, three-quarter front view facing slightly right. Lighting: soft upper-left key light with restrained mint luminous accents. Palette: indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE only. Background must be actual transparent alpha; no painted checkerboard, no scenery, no ground, no shadow plane, no text, no numbers, no border, no frame, no watermark. Keep all feet and arms inside frame.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-4c52cdcd-2068-4ba0-a57e-34e3d6435011.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n02.json b/assets-source/phase3/records/n02.json new file mode 100644 index 0000000..7a18ada --- /dev/null +++ b/assets-source/phase3/records/n02.json @@ -0,0 +1,12 @@ +{ + "id": "n02", + "display_name": "Grenzmaske", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Breiter Nebeltank mit heller Ovalmaske und mehreren geschichteten Sichelschilden.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: GRENZMASKE, the upgraded heavy shield tank of a nonhuman mist faction. A broad folded-indigo mist body supported by two sturdy short tendril feet, a free-standing large pale oval mask with narrow mint eyes at the top center, thick layered crescent shield plates wrapping the front and shoulders into a wide defensive shell. Violet and pale mist shield layers are the main identifying shape; visibly much wider and tougher than a basic compact mask spirit. No weapon, no human face, no hood, no human wizard. Style: polished faceted illustration, broad matte low-poly-like faces, few bold clean shapes, readable at 48px. Composition: single entire unit centered in square canvas with transparent margins, figure occupies 75-80 percent, three-quarter front view facing slightly right. Lighting soft from upper left, restrained mint luminous accents. Palette only indigo #45456F, violet #9578CF, mist white-blue #C4D6E5 and mint #82DBCE. Actual transparent alpha background required; no fake checkerboard, scenery, ground, shadow plane, letters, numbers, frame, border or watermark. All body parts inside canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-567573da-430b-4279-b9b9-a92c9ddefe48.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n03.json b/assets-source/phase3/records/n03.json new file mode 100644 index 0000000..6aa8262 --- /dev/null +++ b/assets-source/phase3/records/n03.json @@ -0,0 +1,12 @@ +{ + "id": "n03", + "display_name": "Fadentänzer", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Schlanker maskierter Nebeltänzer mit zwei versetzt geführten Fadenklingen und langen Standranken.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: FADENTÄNZER, a slim agile nonhuman mist-spirit melee dancer. A small pale free-standing oval mask with mint eyes floats above a narrow body formed of folded indigo and violet ribbon-like mist. Two graceful long crescent forearms each carry a short thin pale thread-blade, kept thick enough to read as an icon. Two long folded tendril legs in a poised dancing stance, one arm diagonally high and the other low; clear balanced silhouette, no floor. No human face, no hood, no wizard, no clothes. Style: polished faceted illustration, broad matte low-poly-like planar surfaces, few large clean shapes, simplified for readability at 48px. Entire single full-body creature centered and occupying 75-80 percent square canvas, transparent margin on all sides. Three-quarter front view facing slightly right. Soft upper-left lighting; palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard picture, no backdrop, no scenery, no ground, no shadow plane, no text, no frame, no border, no watermark. Keep entire blades and feet in frame.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-d9cf6ff2-d5c7-4a8b-8e17-e0308494baba.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n04.json b/assets-source/phase3/records/n04.json new file mode 100644 index 0000000..43ee6a6 --- /dev/null +++ b/assets-source/phase3/records/n04.json @@ -0,0 +1,12 @@ +{ + "id": "n04", + "display_name": "Saumzertrenner", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Hoher Nebelklingenkrieger mit Sichelkamm und großer geöffneter Sichelschere.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: SAUMZERTRENNER, an upgraded nonhuman mist-spirit melee dancer and seam cutter. Tall strong but narrow folded-indigo and violet ribbon-mist body, two planted tendril feet, free-standing pale oval mask with mint eyes and a tall simple crescent crest. The character holds ONE spectacular oversized OPEN PAIR OF SCISSORS made of two wide sweeping crescent blades with a clearly visible round mint pivot; weapon placed diagonally across the body and extending to the side so its scissor silhouette is unmistakable. A stronger more dramatic upgrade of a slim two-blade mist dancer. Nonhuman faceted mist anatomy, no human face, no hood, no wizard, no cloth robes. Style polished faceted strategy-game illustration with broad matte low-poly-like planar surfaces, simplified large shapes readable at 48px. Entire single creature and scissors centered in square canvas with generous transparent margin, occupy 75-80 percent, three-quarter front view facing slightly right. Soft upper-left light. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard image, no scenery, no ground, no shadow plane, no letters, no border, frame or watermark. All blades and feet remain in canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-0b40c2ae-fee5-4854-813c-e3e9dd49372a.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n05.json b/assets-source/phase3/records/n05.json new file mode 100644 index 0000000..e1bb3bf --- /dev/null +++ b/assets-source/phase3/records/n05.json @@ -0,0 +1,12 @@ +{ + "id": "n05", + "display_name": "Fernflüsterer", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Schmale gefaltete Maskenfigur mit langem Flüsterhorn und mintfarbener Schallöffnung.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: FERNFLÜSTERER, a nonhuman mist-spirit sharpshooter. A thin curved indigo and violet folded-mist body on two planted tendril feet, one pale narrow oval floating mask with mint slit eyes, two crescent arms aiming ONE LONG TUBULAR WHISPER HORN forward diagonally toward the right. Horn is a simple pale straight-to-gently-curved tube with a small flared round opening and mint bore, unmistakable hollow acoustic instrument; not a bow or gun. Compact base-tier design, broad readable horn and minimal details. Nonhuman mask creature, no human face, no hood, no wizard or clothes. Style: polished faceted fantasy strategy-game illustration, broad matte low-poly-like faces, large clean shapes readable at 48px. Full body including horn centered on square canvas with transparent margins, 75-80 percent occupancy. Three-quarter front view facing slightly right. Soft upper-left key light, restrained mint glow. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background required; no checkerboard drawing, backdrop, scenery, floor, ground, shadow plane, letters, numbers, frame, border or watermark. All horn and feet inside canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-9eb219ea-b82f-4cb3-81af-261ecda521df.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n06.json b/assets-source/phase3/records/n06.json new file mode 100644 index 0000000..605f345 --- /dev/null +++ b/assets-source/phase3/records/n06.json @@ -0,0 +1,12 @@ +{ + "id": "n06", + "display_name": "Fernrufer", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Aufgewerteter Nebelrufer mit zwei weit geschwungenen Resonanzhörnern und mintfarbenen Schallöffnungen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: FERNRUFER, an upgraded nonhuman mist-spirit ranged caller. A tall folded-indigo and violet mist body, two firmly planted tendril feet, narrow free-standing pale oval mask with mint eye slits, broad upward crescent shoulders supporting EXACTLY TWO large sweeping curved resonance horns. One horn rises on each side of the body and curves forward, both visibly hollow with large flared pale openings and mint interiors, separate clear horn silhouettes. Two crescent arms gesture forward between the horns. Stronger fuller silhouette than a thin spirit with a single whisper tube. No human face, no human clothing, no hood, no wizard, no bow or gun. Style polished faceted fantasy strategy-game illustration with broad matte low-poly-like planes, bold simple shapes, readable at 48px. Single full-body creature and both horns fully inside square canvas, centered with generous transparent margins, occupy 75-80 percent. Three-quarter front view facing slightly right. Soft light from upper left, restrained luminous mint accents. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard image, scenery, ground, floor, shadow plane, text, numbers, border, frame or watermark.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-44a7e03a-f575-4c8b-b57b-2bca7484addf.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n07.json b/assets-source/phase3/records/n07.json new file mode 100644 index 0000000..62f039f --- /dev/null +++ b/assets-source/phase3/records/n07.json @@ -0,0 +1,12 @@ +{ + "id": "n07", + "display_name": "Glockenschlepper", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Gedrungener Nebelträger mit großer heller Glocke und deutlich sichtbarem mintfarbenem Klöppel.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: GLOCKENSCHLEPPER, a squat nonhuman mist spirit carrying one oversized bell. Short broad folded-indigo and violet mist body, two stubby planted tendril feet, small free-standing pale oval mask with mint eye slits above the bell, two short crescent arms firmly carrying a HUGE SINGLE PALE VIOLET BELL in front of its belly. Bell has a broad flared rim and a clearly visible dark hollow mouth and mint clapper; plain broad facets without ornate engravings. Its heavy burden and squat silhouette identify a base-tier area-damage unit. No human face, no hood, no wizard, no robes. Style polished faceted fantasy strategy-game illustration, broad matte low-poly-like faces, few simple bold shapes readable at 48px. Entire one creature and bell centered on square canvas, 75-80 percent canvas with generous transparent margins, three-quarter front view facing slightly right. Soft upper-left key light, restrained mint accents. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard image, scenery, ground, floor, shadow plane, text, numbers, border, frame or watermark. Keep all feet and bell in frame.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-70846764-a373-4cc6-a9e8-1c4d98908508.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n08.json b/assets-source/phase3/records/n08.json new file mode 100644 index 0000000..3c80e8a --- /dev/null +++ b/assets-source/phase3/records/n08.json @@ -0,0 +1,12 @@ +{ + "id": "n08", + "display_name": "Hohlgeläut", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Hoher lebender Kathedralenglockenkörper mit drei Sichelspitzen und mintfarbenem Klöppel im offenen Brustraum.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: HOHLGELÄUT, an upgraded nonhuman mist bell spirit. One large hollow cathedral-bell BODY, tall and imposing, shaped as a broad flared violet bell with three simple upward pale crescent spires and a huge dark arched hollow opening in the front. A luminous mint clapper suspended inside the hollow chest. Small pale oval mask with mint eyes hovering at the top of the arch; heavy indigo folded mist tendril legs planted below the bell, two short crescent arms at the sides. This must read as ONE CREATURE whose body is a cathedral bell, not a building or a spirit carrying a bell; bold broad base and taller upgraded silhouette. No human anatomy, no hood, no wizard, no robes, no architectural scenery. Style polished faceted fantasy strategy-game illustration, broad matte low-poly-like planar surfaces, sparse large clean shapes readable at 48px. Entire single creature centered in square canvas, 75-80 percent occupancy with generous transparent margin, three-quarter front view facing slightly right. Soft upper-left light. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background required; no checkerboard picture, scenery, ground, floor, shadow plane, text, numbers, border, frame or watermark. All spires and feet inside canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-eac712a9-9b56-4963-9bca-6f9cc8a6f9b5.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n09.json b/assets-source/phase3/records/n09.json new file mode 100644 index 0000000..ad70185 --- /dev/null +++ b/assets-source/phase3/records/n09.json @@ -0,0 +1,12 @@ +{ + "id": "n09", + "display_name": "Maskenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Kompakter maskierter Nebelsänger mit einer frei schwebenden Begleitmaske über dem erhobenen Sichelarm.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: MASKENKANTOR, a small nonhuman mist-spirit support singer. Compact folded-indigo and violet mist body supported by two short planted tendril feet, one pale oval face-mask with narrow mint eyes and an open small singing mouth; crescent arms gently conducting. EXACTLY ONE additional smaller pale mask floats separately above the raised hand on the right with visible empty transparent separation. Two masks total, only one whole creature. A simple pale crescent collar and broad folded body imply light ceremonial armor, never human clothing or hood. The companion mask shows the support role without particle clutter. Base-tier, simple compact silhouette. No human face, no hooded wizard, no microphone, no music notes. Style: polished faceted fantasy strategy-game illustration, broad matte low-poly-like surfaces, bold simple shapes readable at 48px. Entire figure and companion mask centered in square canvas, occupy 75-80 percent with ample transparent margins. Three-quarter front view facing slightly right; soft upper-left light. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard drawing, scenery, ground, floor, shadow plane, text, numbers, border, frame or watermark. Keep every part inside canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-43662c7b-86d0-4167-95ee-9ec39d2eb8ac.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/n10.json b/assets-source/phase3/records/n10.json new file mode 100644 index 0000000..f9b3fa4 --- /dev/null +++ b/assets-source/phase3/records/n10.json @@ -0,0 +1,12 @@ +{ + "id": "n10", + "display_name": "Vielstimmenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "description_de": "Gekrönter Nebelchor-Kantor mit breitem Sichelkragen und drei getrennt schwebenden Begleitmasken.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit icon, square transparent PNG. Subject: VIELSTIMMENKANTOR, an upgraded nonhuman choir spirit. ONE central tall folded-indigo and violet mist body standing on two broad planted tendril feet, one large pale oval singing mask with mint slit eyes and open mouth, topped by a bold three-point crescent crown. Two wide crescent conducting arms. EXACTLY THREE smaller pale singing masks float around the central upper body: one at left shoulder height, one at right shoulder height, one above-right; each separated from body and other masks by transparent space, no extra bodies. Four masks total, but one single game unit. Layered pale crescent collar and full broad folds make a stronger imposing support upgrade of a small singer with one companion mask. No human face, no hood or wizard, no robes, no musical notation. Style polished faceted fantasy strategy-game illustration, broad matte low-poly-like faces, large clean shapes readable at 48px, avoid tiny decoration and particle clutter. Entire single creature and all three floating masks centered in square canvas with generous margins, occupy 75-80 percent. Three-quarter front view facing slightly right. Soft upper-left light, restrained mint glow. Palette indigo #45456F, violet #9578CF, pale mist #C4D6E5, mint #82DBCE. Actual transparent alpha background; no checkerboard drawing, scene, ground, floor, shadow plane, text, numbers, border, frame or watermark. Keep all masks and feet inside canvas.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-9fa0cc3d-c29c-4daf-8d30-4ee5bbc9650c.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/res_core.json b/assets-source/phase3/records/res_core.json new file mode 100644 index 0000000..fe40cc7 --- /dev/null +++ b/assets-source/phase3/records/res_core.json @@ -0,0 +1,12 @@ +{ + "id": "res_core", + "display_name": "Kernleben", + "faction": "resources", + "kind": "resource_icon", + "description_de": "Korallfarbenes facettiertes Kristallherz in einer kleinen Messingfassung.", + "prompt": "Use case: stylized-concept. Asset type: standalone resource UI icon for original fantasy strategy game Saumwacht. Faceted illustrated game UI art, large simple flat matte planes, crisp graphic edges, restrained shading, very clear shape readable at 48px and 256px. Single coherent centered icon on square canvas, whole object visible, occupies around 75% canvas with transparent margins all sides. Three-quarter front view facing slightly right, soft neutral upper-left key light. Palette warm brass gold #D9A441, pale mint teal #82DBCE, coral #E9967C, slate #536375. Truly transparent RGBA alpha background, no checkerboard pixels, no ground, no cast shadow, no border or frame, no badge background, no text, no letters, no numerals, no logos, no watermark. Avoid photorealism, glossy rendering and tiny texture.\nSubject: One chunky faceted CORAL crystal HEART cradled in a tiny warm brass support base with two short protective prongs. Heart shape has two broad rounded angular lobes and a clear pointed bottom, instantly readable as life resource. Coral #E9967C dominates, warm brass #D9A441 cradle, minimal slate underside. Broad matte crystal planes, tiny restrained highlight, no luminous halo.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-725253b1-7fe0-4a4b-a960-3b5fa731b902.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/resources/res_core.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/res_gold.json b/assets-source/phase3/records/res_gold.json new file mode 100644 index 0000000..20a54b4 --- /dev/null +++ b/assets-source/phase3/records/res_gold.json @@ -0,0 +1,12 @@ +{ + "id": "res_gold", + "display_name": "Gold", + "faction": "resources", + "kind": "resource_icon", + "description_de": "Eine große facettierte Goldmünze mit zwei kleineren Münzen.", + "prompt": "Use case: stylized-concept. Asset type: standalone resource UI icon for original fantasy strategy game Saumwacht. Faceted illustrated game UI art, large simple flat matte planes, crisp graphic edges, restrained shading, very clear shape readable at 48px and 256px. Single coherent centered icon on square canvas, whole object visible, occupies around 75% canvas with transparent margins all sides. Three-quarter front view facing slightly right, soft neutral upper-left key light. Palette warm brass gold #D9A441, pale mint teal #82DBCE, coral #E9967C, slate #536375. Truly transparent RGBA alpha background, no checkerboard pixels, no ground, no cast shadow, no border or frame, no badge background, no text, no letters, no numerals, no logos, no watermark. Avoid photorealism, glossy rendering and tiny texture.\nSubject: A chunky golden coin angled three-quarter toward camera with exactly two smaller golden coins nestled at its lower right, a compact grouped resource icon. Broad faceted bevels, simple blank coin faces with a subtle geometric inset but no currency signs and no letters. Warm gold dominates with darker brass edge planes.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-2caa13f0-211c-4444-9f78-bf068af50ac5.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/resources/res_gold.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/res_income.json b/assets-source/phase3/records/res_income.json new file mode 100644 index 0000000..7a47c54 --- /dev/null +++ b/assets-source/phase3/records/res_income.json @@ -0,0 +1,12 @@ +{ + "id": "res_income", + "display_name": "Einkommen", + "faction": "resources", + "kind": "resource_icon", + "description_de": "Messingsiegel mit drei von links nach rechts ansteigenden Münzstapeln.", + "prompt": "Use case: stylized-concept. Asset type: standalone resource UI icon for original fantasy strategy game Saumwacht. Faceted illustrated game UI art, large simple flat matte planes, crisp graphic edges, restrained shading, very clear shape readable at 48px and 256px. Single coherent centered icon on square canvas, whole object visible, occupies around 75% canvas with transparent margins all sides. Three-quarter front view facing slightly right, soft neutral upper-left key light. Palette warm brass gold #D9A441, pale mint teal #82DBCE, coral #E9967C, slate #536375. Truly transparent RGBA alpha background, no checkerboard pixels, no ground, no cast shadow, no border or frame, no badge background, no text, no letters, no numerals, no logos, no watermark. Avoid photorealism, glossy rendering and tiny texture.\nSubject: A single thick faceted brass seal medallion with THREE bold raised stacks of coins on its face, stepping upward left to right from one to three to five coins, conveying income growth visually. Coin stacks should read like three ascending bar-chart columns made of coins, simplified broad surfaces, slate inset contrast behind raised gold geometry. No arrows required, absolutely no lettering, numerals or currency symbols. Seal itself is the object, no surrounding UI frame.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-02bfd968-9507-46c5-8818-1e6eb87ff9e4.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/resources/res_income.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/res_sparks.json b/assets-source/phase3/records/res_sparks.json new file mode 100644 index 0000000..fe851e7 --- /dev/null +++ b/assets-source/phase3/records/res_sparks.json @@ -0,0 +1,12 @@ +{ + "id": "res_sparks", + "display_name": "Funken", + "faction": "resources", + "kind": "resource_icon", + "description_de": "Kleines Messing-Glasgefäß mit leuchtender mintfarbener Funkenenergie.", + "prompt": "Use case: stylized-concept. Asset type: standalone resource UI icon for original fantasy strategy game Saumwacht. Faceted illustrated game UI art, large simple flat matte planes, crisp graphic edges, restrained shading, very clear shape readable at 48px and 256px. Single coherent centered icon on square canvas, whole object visible, occupies around 75% canvas with transparent margins all sides. Three-quarter front view facing slightly right, soft neutral upper-left key light. Palette warm brass gold #D9A441, pale mint teal #82DBCE, coral #E9967C, slate #536375. Truly transparent RGBA alpha background, no checkerboard pixels, no ground, no cast shadow, no border or frame, no badge background, no text, no letters, no numerals, no logos, no watermark. Avoid photorealism, glossy rendering and tiny texture.\nSubject: A single small squat glass vessel framed by two broad brass bands and a chunky brass stopper, containing one vivid pale mint energy spark cluster. A simple slate base, large clear window allowing bright teal energy to be seen. Faceted stylized glass planes, not glossy photoreal glass. No glow leaking onto the transparent background, no floating particles outside vessel.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-e1eacde7-ae55-41d3-82c5-ec33cbc40437.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/resources/res_sparks.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/s01.json b/assets-source/phase3/records/s01.json new file mode 100644 index 0000000..1358574 --- /dev/null +++ b/assets-source/phase3/records/s01.json @@ -0,0 +1,12 @@ +{ + "id": "s01", + "display_name": "Nadelspäher", + "description_de": "Schlanker maskierter Söldnerspäher mit kompaktem Nadelwerfer.", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy 75–80 percent of canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a thin masked scout mercenary, slim upright silhouette, pointed slate-gray hood and fitted layered dark armor, simple ivory full-face mask, compact handheld dart launcher pointing right, three clearly visible thick spare darts in a rust-red back quiver, narrow limbs and practical boots; original fantasy creature-like scout with no copied character references.", + "faction": "neutral", + "kind": "mercenary_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-acd47e5f-98cd-4047-b9cf-d04833ee91c2.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/s02.json b/assets-source/phase3/records/s02.json new file mode 100644 index 0000000..0e7de1e --- /dev/null +++ b/assets-source/phase3/records/s02.json @@ -0,0 +1,12 @@ +{ + "id": "s02", + "display_name": "Rostschieber", + "description_de": "Gedrungener schwerer Söldner mit Rostpanzer und großem Rammschild.", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy 75–80 percent of canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a squat heavy shield-ram mercenary, wide rust-red layered armor and dark slate body, thick ivory brow guard and tiny inset eyes, huge broad rectangular shield held ahead as a battering ram with a single steel wedge along its center, compact heavy legs and a short hammerlike free fist; low rectangular silhouette emphasizing a defensive shield.", + "faction": "neutral", + "kind": "mercenary_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-119c1a0e-881e-4696-a764-be3d802eab15.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/s03.json b/assets-source/phase3/records/s03.json new file mode 100644 index 0000000..2d72324 --- /dev/null +++ b/assets-source/phase3/records/s03.json @@ -0,0 +1,12 @@ +{ + "id": "s03", + "display_name": "Dunstsänger", + "description_de": "Verhüllter violetter Dunstsänger mit großem Resonanzhorn.", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy 75–80 percent of canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a draped ethereal mist-singer mercenary, elongated bell-shaped dark slate and muted violet robe with broad faceted folds, small simple ivory mask inside a deep hood, two slender hands holding a large rust-bronze resonance horn with an open flared bell pointing to the right, a few contained violet wisps tucked inside the silhouette; full figure with no platform or ground.", + "faction": "neutral", + "kind": "mercenary_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-977e27d0-9bb9-44ca-8b66-bfbbf04e70ce.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/s04.json b/assets-source/phase3/records/s04.json new file mode 100644 index 0000000..d61dd25 --- /dev/null +++ b/assets-source/phase3/records/s04.json @@ -0,0 +1,12 @@ +{ + "id": "s04", + "display_name": "Keilbrecher", + "description_de": "Schwerer dunkelgrauer Keilbrecher mit großem Keilhammer.", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy 75–80 percent of canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a heavy dark-steel walking wedge-hammer mercenary, powerful broad-shouldered stocky warrior, massive blocky slate-gray armor with restrained rust-red accents, simple ivory faceplate, two heavy hands gripping a gigantic wedge-shaped hammer with a clear triangular chisel head held diagonally across the body, short sturdy legs and wide boots; strong triangle and block silhouette.", + "faction": "neutral", + "kind": "mercenary_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-3f1a6bd4-4a83-46c3-b479-e79b4716c1eb.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/s05.json b/assets-source/phase3/records/s05.json new file mode 100644 index 0000000..3028045 --- /dev/null +++ b/assets-source/phase3/records/s05.json @@ -0,0 +1,26 @@ +{ + "id": "s05", + "display_name": "Risszehrer", + "description_de": "Hohler Risszehrer mit mintviolettem Schlund und magischer Entzugskugel.", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy only 65 percent of canvas height; make the figure relatively small with wide empty transparent margins on ALL sides. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a tall hollow rift-feeding creature mercenary, original alien fantasy silhouette, long angular slate-gray shell torso with a large hollow chest opening glowing faint mint and violet, short compact ivory broken-arc crown around a faceless dark head with a restrained mint-violet mouth slit, two long tapering arms, one claw cradling a single small glowing mint-violet healing-drain orb close to its chest, long digitigrade legs; thin eerie silhouette with a very readable empty chest hole, no gore. Framing is critical: the entire small creature must sit within the central 65 percent of the square, crown tip far below top edge, feet far above bottom edge. Actual transparent PNG alpha, not an illustrated checkerboard.", + "faction": "neutral", + "kind": "mercenary_icon", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-d505eb20-988a-49d7-b821-be49d87c14ba.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png", + "status": "generated", + "iterations": [ + { + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-6384b126-c087-4d51-b9f7-43abd9b7e6b5.png", + "prompt": "Use case: stylized-concept. Asset type: original neutral mercenary UNIT ICON for Saumwacht, a single individual PNG cutout. Create a brand-new image. Style: crisp faceted illustrated low-poly fantasy, strong chunky planar shapes and simple matte shading, coherent premium strategy-game icon, not photorealistic. Composition: square 1:1 canvas, whole single figure centered, all parts visible with comfortable transparent margin, occupy 75–80 percent of canvas. Three-quarter front view looking toward viewer's right. Lighting: soft key from upper left and restrained ambient fill. Palette: slate #536375 and rust #A8654D with ivory #D8D2BF, restrained violet #9578CF; only the rift creature may add a small mint glow. Keep broad masses readable at 48px. Scene: genuinely transparent background with preserved alpha; no checkerboard pattern drawn into the image. No ground, no shadow plane, no frame, no text, no lettering, no logos, no border, no watermark, no unrelated props, no other characters, no realistic texture, no excessive microdetail. Subject: a tall hollow rift-feeding creature mercenary, original alien fantasy silhouette, long angular slate-gray shell torso with a large hollow chest opening glowing faint mint and violet, ivory broken-arc crown around a faceless dark head with a restrained mint-violet mouth slit, two long tapering arms, one claw cradling a single small glowing mint-violet healing-drain orb close to its chest, long digitigrade legs; thin eerie silhouette with a very readable empty chest hole, no gore.", + "status": "rejected", + "reason_de": "Kronenspitze am oberen Bildrand angeschnitten." + }, + { + "source_path": "/home/martin/.codex/generated_images/01a096fb-2a90-7821-8332-7507717ed80a/exec-97910932-6bdd-4856-881d-6fceea251897.png", + "prompt": "Use case: precise-object-edit. Edit target: this Risszehrer neutral mercenary icon. Correct only framing: extend the genuine transparent canvas and present the same entire creature at about 78 percent canvas height in a square 1:1 image, centered, with at least 10 percent empty transparent margin above the fully visible ivory crown tips and below the fully visible feet. Complete the tiny crown tip currently clipped by the top edge. Preserve the creature's exact identity, colors, faceted matte style, three-quarter front view looking right, upper-left lighting, hollow chest, mint-violet orb, limbs, pose and proportions. Do not crop any part. Actual transparent alpha outside subject; no background color, checkerboard, ground, shadow plane, text, frame or extra objects.", + "status": "rejected", + "reason_de": "Sichtbares Karomuster statt sauberem transparentem Hintergrund." + } + ] +} diff --git a/assets-source/phase3/records/type_armor_aether.json b/assets-source/phase3/records/type_armor_aether.json new file mode 100644 index 0000000..544690b --- /dev/null +++ b/assets-source/phase3/records/type_armor_aether.json @@ -0,0 +1,12 @@ +{ + "id": "type_armor_aether", + "display_name": "Ätherische Rüstung", + "faction": "types", + "kind": "type_icon", + "description_de": "Hohler violetter Geisterschild mit mintfarbener Innenkante und transparentem Innenraum.", + "prompt": "Use case: stylized-concept. Asset type: ONE fantasy strategy-game UI armor-type icon, square transparent PNG. Subject: AETHER ARMOR, a SINGLE HOLLOW GHOST SHIELD. Broad pointed shield silhouette formed from a thick faceted violet spectral rim with mint inner edge; center is a large genuinely EMPTY TRANSPARENT opening, no opaque face plate or backing. Top rim has two subtle upward crescent tips and bottom ends in one smooth pointed tip. Two very short broad tapered ghost wisps attach to lower rim, still one compact clear object. Clearly magical hollow defensive shell, no face, no eyes, no skull, no character. It must read distinctly from a metal shield at 32px. Polished faceted flat UI illustration matching matte low-poly fantasy art, a few broad matte planar shapes with restrained mint glow, crisp clean silhouette, no particles or small decoration. Slight three-quarter perspective turned a little right, soft upper-left lighting. Palette violet #9578CF, mint #82DBCE, graphite #292B35 for shadow facets, tiny ivory #D8CEC0 highlights. Single full icon centered in square canvas, 75 percent occupancy with generous transparent margins. Actual transparent alpha background and transparent center, no checkerboard picture, scenery, ground, cast shadow, badge, backing disc, text, letters, numbers, frame, border or watermark.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-dd3d2287-ed73-4ecc-9f67-c61bb1512721.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_armor_aether.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/type_armor_heavy.json b/assets-source/phase3/records/type_armor_heavy.json new file mode 100644 index 0000000..b3082f1 --- /dev/null +++ b/assets-source/phase3/records/type_armor_heavy.json @@ -0,0 +1,12 @@ +{ + "id": "type_armor_heavy", + "display_name": "Schwere Rüstung", + "faction": "types", + "kind": "type_icon", + "description_de": "Breite schwere Schildplatte aus drei Graphitstahllagen mit hellen Kanten und Messingverstärkung.", + "prompt": "Use case: stylized-concept. Asset type: ONE fantasy strategy-game UI armor-type icon, square transparent PNG. Subject: HEAVY ARMOR, a SINGLE broad thick layered STEEL SHIELD PLATE with squared upper shoulders and a blunt pointed bottom. Three overlapping large graphite steel armor layers across the front, thick visible beveled ivory-gray steel edges, a small simple brass reinforcing band along the outer edge. Extremely stout heavy silhouette, visibly thick and rigid, no leather strap, no emblem, no symbols. It must read as heavy metal armor at 32px. Polished faceted flat UI illustration matching matte low-poly fantasy art, only a few broad planar faces, clean bold silhouette, no tiny rivets or engravings. Slight three-quarter perspective turned a little right, soft upper-left lighting. Palette graphite #292B35, ivory #D8CEC0 for steel highlights, brass #D9A441 minimal trim. Entire single object centered in square canvas, 75 percent occupancy with generous transparent margins. Actual transparent alpha background required; no checkerboard image, scene, ground, cast shadow, badge, backing disc, text, letters, numbers, frame, border or watermark.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-2a33cdd9-c6e6-41ad-abe3-0848690d79bc.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_armor_heavy.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/type_armor_light.json b/assets-source/phase3/records/type_armor_light.json new file mode 100644 index 0000000..3b4414f --- /dev/null +++ b/assets-source/phase3/records/type_armor_light.json @@ -0,0 +1,12 @@ +{ + "id": "type_armor_light", + "display_name": "Leichte Rüstung", + "faction": "types", + "kind": "type_icon", + "description_de": "Dünne blattförmige Lederpanzerplatte in warmem Ocker mit einfachem Graphitriemen.", + "prompt": "Use case: stylized-concept. Asset type: ONE fantasy strategy-game UI armor-type icon, square transparent PNG. Subject: LIGHT ARMOR, a SINGLE thin elongated LEAF-SHAPED LEATHER ARMOR PLATE, pointed bottom, softly rounded upper shoulders, with a subtle central folded ridge and one simple narrow graphite leather strap wrapping the middle. Warm brass-ochre matte leather main face, ivory edge highlights, thin flexible edge visibly unlike a bulky metal shield. No plant leaf veins, no actual foliage, no full body armor, no person. Must read as a light leather protective plate at 32px. Polished faceted flat UI illustration matching matte low-poly fantasy art, only a few broad planes and crisp simple silhouette, no tiny stitches or detailed texture. Slight three-quarter perspective turned a little right; soft upper-left key light. Palette graphite #292B35, ivory #D8CEC0, brass #D9A441 interpreted as warm matte leather. Whole single object centered in square canvas, 75 percent occupancy, generous transparent margins. Actual transparent alpha background; no checkerboard picture, scenery, ground, cast shadow, badge, backing disc, text, numbers, frame, border or watermark.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-4112c2a0-2ec6-47e2-8592-9ad3bf0ea66d.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_armor_light.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/type_damage_blade.json b/assets-source/phase3/records/type_damage_blade.json new file mode 100644 index 0000000..c8537f2 --- /dev/null +++ b/assets-source/phase3/records/type_damage_blade.json @@ -0,0 +1,12 @@ +{ + "id": "type_damage_blade", + "display_name": "Klinge", + "faction": "types", + "kind": "type_icon", + "description_de": "Einzelne gebogene Elfenbeinklinge mit Messingparierstange und Graphitgriff.", + "prompt": "Use case: stylized-concept. Asset type: one fantasy strategy-game UI damage-type icon, square transparent PNG. Subject: BLADE DAMAGE, a SINGLE short broad curved ivory blade with a simple brass crossguard and short graphite grip. Orient diagonally lower left to upper right, point upward; one clean sweeping cutting edge. It must read unmistakably as a blade at 32px. Style: polished faceted flat UI illustration matching matte low-poly fantasy unit art, only a few broad planar shapes, crisp silhouette, no tiny engravings, no excessive texture. Slight three-quarter perspective and soft light from upper left. Palette graphite #292B35, ivory #D8CEC0, brass #D9A441. Entire object centered, about 75 percent of square canvas, generous transparent margin on all sides. Actual transparent alpha background, no checkerboard picture, no ground, no scene, no cast shadow, no badge, no circular disc, no frame, no letters, no numbers, no watermark. Exactly one isolated icon.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-c7909917-44f8-4e6f-8809-3c86ff441734.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_damage_blade.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/type_damage_pierce.json b/assets-source/phase3/records/type_damage_pierce.json new file mode 100644 index 0000000..252e33f --- /dev/null +++ b/assets-source/phase3/records/type_damage_pierce.json @@ -0,0 +1,12 @@ +{ + "id": "type_damage_pierce", + "display_name": "Durchschlag", + "faction": "types", + "kind": "type_icon", + "description_de": "Lange Messingpfeilspitze durchstößt eine kleine graphitfarbene Rautenplatte.", + "prompt": "Use case: stylized-concept. Asset type: ONE fantasy strategy-game UI damage-type icon, square transparent PNG. Subject: PIERCING DAMAGE, a SINGLE long sharp brass arrowhead with a short narrow graphite shaft visibly punching THROUGH a small thick dark graphite diamond-shaped plate. Composition diagonal lower left to upper right: arrowhead extends prominently above-right of plate, short shaft extends below-left, plate surrounds one tight angular puncture hole. Long brass spear-like triangular point dominates, small plate is secondary. No explosion, no extra arrows, no loose fragments. Must read unmistakably as piercing impact at 32px. Polished faceted flat UI illustration coherent with matte low-poly fantasy art, only a few large planar shapes, crisp bold silhouette, minimal detail and no engravings. Slight three-quarter perspective, soft light from upper left. Palette graphite #292B35, ivory #D8CEC0 for small highlight edge, brass #D9A441. Center entire object group in square canvas, 75 percent occupancy, generous transparent margins. Actual transparent alpha background, no checkerboard picture, ground, scene, cast shadow, badge, disc, frame, letters, numbers or watermark. Exactly one icon.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-f0526b22-0c7b-4737-9a6c-f26cd416a116.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_damage_pierce.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/type_damage_pulse.json b/assets-source/phase3/records/type_damage_pulse.json new file mode 100644 index 0000000..aaa0844 --- /dev/null +++ b/assets-source/phase3/records/type_damage_pulse.json @@ -0,0 +1,12 @@ +{ + "id": "type_damage_pulse", + "display_name": "Impuls", + "faction": "types", + "kind": "type_icon", + "description_de": "Mintfarbener facettierter Sternkern zwischen zwei offenen graphitfarbenen Ringhälften.", + "prompt": "Use case: stylized-concept. Asset type: ONE fantasy strategy-game UI damage-type icon, square transparent PNG. Subject: PULSE DAMAGE, a compact glowing MINT GEOMETRIC STAR-ORB inside one thick OPEN GRAPHITE RING. Core is a solid faceted orb with four short broad diamond-like energy points, NOT a spiky explosion, not a sun face. Dark ring surrounds the core but has two clearly open gaps on opposite sides, with transparent space between the core and ring; no outer badge or backing disc. Bold round compact silhouette with mint center unmistakable at 32px. Polished faceted flat UI illustration matching matte low-poly fantasy art, only a few big planar surfaces, crisp shapes and extremely restrained glow entirely near the core. Slight three-quarter perspective, soft upper-left lighting. Palette graphite #292B35, mint #82DBCE, tiny ivory #D8CEC0 highlights; no extra colors. Entire icon centered in square canvas, 75 percent occupancy, generous transparent margins. Actual transparent alpha background; no checkerboard image, ground, scenery, cast shadow, surrounding particles, circular badge, text, letters, numbers, border, frame or watermark. Exactly one isolated icon.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-59c9c62a-5ffe-4820-bc71-556f2dc679bb.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/types/type_damage_pulse.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/ui_button_disabled.json b/assets-source/phase3/records/ui_button_disabled.json new file mode 100644 index 0000000..07ae2c9 --- /dev/null +++ b/assets-source/phase3/records/ui_button_disabled.json @@ -0,0 +1,43 @@ +{ + "id": "ui_button_disabled", + "display_name": "Button – Deaktiviert", + "faction": "ui", + "kind": "ui_button", + "description_de": "Deaktivierter Button in entsättigtem Schiefergrau und gedämpftem Messing.", + "prompt": "Use case: stylized-concept. Create one clean standalone reusable DISABLED STATE button graphic for original fantasy strategy game Saumwacht. Wide horizontal aspect ratio 3:1, front facing perfectly flat orthographic UI view, not tilted or isometric. One long desaturated dark slate #394550 rectangular central button surface, thin layered DULL MUTED GRAY-BROWN BRASS bevel border (desaturated brass, not bright gold), dark basalt #292B35 outside rim, small tasteful geometric folded corner accents, softly chamfered corners, subtle upper-left lighting. Reduced highlights and contrast make the button visibly inactive. Faceted matte illustrated game UI art with broad crisp color planes, matches hand-illustrated stone-and-brass strategy icons. HUGE plain empty uninterrupted label area in center, no text or symbols anywhere. Symmetric exact geometry. Button occupies about 85% canvas width and 65% height with transparent safety margin on all sides. Genuine RGBA transparency outside the button; button interior itself is solid opaque dark slate. No checkerboard, no opaque background, no cast shadow, no mockup, no multiple buttons, no letters, no watermark, no colored glow. Production-ready isolated game UI element, no flourishes extending outward. Actual transparent background required: output a PNG with an alpha channel, not a visual depiction of transparency.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-2e37bcef-6fd2-4110-b43d-4033bdc211aa.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_disabled.png", + "status": "generated", + "reference_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_normal.png", + "iterations": [ + { + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-3577da02-efb1-4648-8f55-0b4969fa5667.png", + "prompt": "Edit the supplied normal UI button for the original fantasy strategy game SAUMWACHT. Keep the exact canvas aspect ratio, silhouette, outside alpha margin, chamfered corners, all brass geometric corner details, and broad blank center identical to reference. This is a matching interaction state of the same control, not a redesign. Straight-on orthographic view; matte illustrated low-poly facets, top-left light; no text, icons, symbols, numbers, watermark, external shadow, or glow outside the silhouette. Preserve genuine transparent background and opaque center. Create the DISABLED state: desaturate face to slate #536375 with dark values, desaturate brass to dull grey-brown, reduce contrast and highlights. Entire face and border remain fully opaque; only outside stays transparent.", + "reason": "Baked checkerboard; rejected because alpha channel absent." + }, + { + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-292a41ce-3b52-42c1-9190-7829cc3285e1.png", + "prompt": "Remove the checkerboard backdrop from this UI button asset completely. It is accidentally painted into the image and must be erased to real PNG alpha transparency, not replaced with black, white, grey, or a new checker pattern. Keep every pixel of the actual button artwork, shape, size, position, center fill, metal edge and corner ornament unchanged. Preserve the source 3:1 canvas and button bounding box. No redesign or relighting. Outside the chamfered outer dark silhouette must have alpha=0. The button itself must remain opaque. Return a genuinely transparent RGBA PNG cutout of only the button, with no shadow outside, no background pattern.", + "reason": "RGB with painted checkerboard; replaced after verified RGBA generation." + } + ], + "generation_strategy": "fresh generation after reference edit failed transparency", + "alpha_verification": { + "mode": "RGBA", + "width": 2172, + "height": 724, + "extrema": [ + 0, + 255 + ], + "corner_alpha": [ + 0, + 0, + 0, + 0 + ], + "center_alpha": 252, + "note": "Native RGBA output preserved without pixel editing; generated center alpha is 252/255." + } +} diff --git a/assets-source/phase3/records/ui_button_hover.json b/assets-source/phase3/records/ui_button_hover.json new file mode 100644 index 0000000..6625fe0 --- /dev/null +++ b/assets-source/phase3/records/ui_button_hover.json @@ -0,0 +1,48 @@ +{ + "id": "ui_button_hover", + "display_name": "Button – Hover", + "faction": "ui", + "kind": "ui_button", + "description_de": "Hover-Zustand mit hellerem Messingrand und einer schmalen mintfarbenen Innenkante.", + "prompt": "Use case: stylized-concept. Create one clean standalone reusable HOVER STATE button graphic for original fantasy strategy game Saumwacht. Wide horizontal aspect ratio 3:1, front facing perfectly flat orthographic UI view, not tilted or isometric. One long dark petrol #243D47 rectangular central button surface, thin layered bright warm brass #D9A441 bevel border, hairline mint #82DBCE INNER rim, dark basalt #292B35 outside rim, small tasteful geometric folded brass corner accents, softly chamfered corners, neutral upper-left lighting. Faceted matte illustrated game UI art with broad crisp color planes, matches hand-illustrated stone-and-brass strategy icons. HUGE plain empty uninterrupted label area in center, no text or symbols anywhere. Symmetric exact geometry. Button occupies about 85% canvas width and 65% height with transparent safety margin on all sides. Genuine RGBA transparency outside the button; the button interior itself is solid dark petrol. No checkerboard, no opaque background, no cast shadow, no mockup, no multiple buttons, no letters, no watermark. Production-ready isolated game UI element, no flourishes extending outward. Actual transparent background is required: please output a PNG with an alpha channel, not a visual depiction of transparency.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-161237e3-3901-4bbc-bd11-ebb3b5fe9663.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_hover.png", + "status": "generated", + "reference_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_normal.png", + "iterations": [ + { + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-2cb1a707-bff3-49a5-a842-42ecc5578275.png", + "prompt": "Edit the supplied normal UI button for the original fantasy strategy game SAUMWACHT. Keep the exact canvas aspect ratio, silhouette, outside alpha margin, chamfered corners, all brass geometric corner details, and broad blank center identical to reference. This is a matching interaction state of the same control, not a redesign. Straight-on orthographic view; matte illustrated low-poly facets, top-left light; no text, icons, symbols, numbers, watermark, external shadow, or glow outside the silhouette. Preserve genuine transparent background and opaque center. Create the HOVER state: brass border subtly brighter warm gold #D9A441, a very thin restrained mint #82DBCE inner rim, center slightly brighter dark petrol. Keep the label area calm and empty.", + "reason": "Baked checkerboard; rejected because alpha channel absent." + }, + { + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-dc64da6b-4a18-44a5-ae51-e06554e05552.png", + "prompt": "Remove the checkerboard backdrop from this UI button asset completely. It is accidentally painted into the image and must be erased to real PNG alpha transparency, not replaced with black, white, grey, or a new checker pattern. Keep every pixel of the actual button artwork, shape, size, position, center fill, metal edge and corner ornament unchanged. Preserve the source 3:1 canvas and button bounding box. No redesign or relighting. Outside the chamfered outer dark silhouette must have alpha=0. The button itself must remain opaque. Return a genuinely transparent RGBA PNG cutout of only the button, with no shadow outside, no background pattern.", + "reason": "RGB with painted checkerboard; replaced after verified RGBA generation." + }, + { + "source_path": "/home/martin/.codex/generated_images/01a096fb-969b-74f3-a893-5fea0b3fac02/exec-0101f2f9-92df-41a6-ad5d-99a529442c12.png", + "prompt": "Use case: precise-object-edit. Input image is the finished normal-state button and is the exact reference and edit target. Create the matching HOVER state of this SAME fantasy strategy game UI button. Preserve exact 3:1 canvas ratio, position, silhouette, size, flat orthographic front view, all chamfered corners, corner facets, bevel thickness, and large blank dark petrol center. Preserve soft upper-left lighting. Change only the color treatment: brighten the brass bevel slightly to warm gold #D9A441, add a very narrow restrained mint #82DBCE line along the inner bevel, make the dark petrol center slightly brighter. Matte faceted illustrated UI style. Important output: PNG with a real alpha channel, fully transparent alpha=0 everywhere outside the physical button silhouette, while button center and metal are fully opaque. The reference background is transparency: retain genuine transparency, NEVER draw a checkerboard or solid-color backdrop. No glow or shadow outside the silhouette. No text, letters, symbols, icons, numbers or watermark. Return just one button on a truly transparent 3:1 canvas.", + "reason": "Reference edit returned RGB with baked checkerboard; rejected after PNG header check." + } + ], + "generation_strategy": "fresh generation after reference edit failed transparency", + "alpha_verification": { + "mode": "RGBA", + "width": 2172, + "height": 724, + "extrema": [ + 0, + 255 + ], + "corner_alpha": [ + 0, + 0, + 0, + 0 + ], + "center_alpha": 254, + "note": "Native output preserved; center alpha 254 also occurs in the accepted normal template." + } +} diff --git a/assets-source/phase3/records/ui_button_normal.json b/assets-source/phase3/records/ui_button_normal.json new file mode 100644 index 0000000..efe0ca3 --- /dev/null +++ b/assets-source/phase3/records/ui_button_normal.json @@ -0,0 +1,12 @@ +{ + "id": "ui_button_normal", + "display_name": "Button – Normal", + "faction": "ui", + "kind": "ui_button", + "description_de": "Unbeschrifteter petrolfarbener Button mit kantigem Messingrand, dunkler Innenfläche und kleinen geometrischen Eckakzenten.", + "prompt": "Use case: stylized-concept. Create one clean standalone reusable NORMAL STATE button graphic for original fantasy strategy game Saumwacht. Wide horizontal aspect ratio 3:1, front facing perfectly flat orthographic UI view, not tilted or isometric. One long dark petrol #1C2E36 rectangular central button surface, thin layered warm brass #D9A441 bevel border, dark basalt #292B35 outside rim, small tasteful geometric corner accents, softly chamfered corners, neutral upper-left lighting. Faceted matte illustrated game UI art with broad crisp color planes, matches hand-illustrated stone-and-brass strategy icons. HUGE plain empty uninterrupted label area in center, no text or symbols anywhere. Symmetric exact geometry. Button occupies about85%canvaswidth65%height with transparent safety margin on all sides. Genuine RGBA transparency outside the button; the button interior itself is solid dark petrol. No checkerboard, no opaque background, no cast shadow, no mockup, no multiplebuttons, no letters, no watermark. Production-ready isolated gameUI element, no flourishes extending outward.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-4dd8ed27-251c-403e-a98f-2c48db223706.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_normal.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/ui_button_pressed.json b/assets-source/phase3/records/ui_button_pressed.json new file mode 100644 index 0000000..7f89e24 --- /dev/null +++ b/assets-source/phase3/records/ui_button_pressed.json @@ -0,0 +1,13 @@ +{ + "id": "ui_button_pressed", + "display_name": "Button – Gedrückt", + "faction": "ui", + "kind": "ui_button", + "description_de": "Gedrückter Button mit abgedunkelter, eingesenkter Petrolfläche und umgekehrtem Innenrelief.", + "prompt": "Edit the supplied normal UI button for the original fantasy strategy game SAUMWACHT. Keep the exact canvas aspect ratio, silhouette, outside alpha margin, chamfered corners, all brass geometric corner details, and broad blank center identical to reference. This is a matching interaction state of the same control, not a redesign. Straight-on orthographic view; matte illustrated low-poly facets, top-left light; no text, icons, symbols, numbers, watermark, external shadow, or glow outside the silhouette. Preserve genuine transparent background and opaque center. Create the PRESSED state: center recessed inward and darker petrol, inverted inner bevel with dark top and left and restrained lower-right rim highlight. Brass outer edge slightly darker. No displacement of the control geometry.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-4b498a09-0bc1-414f-ae71-05e3de6bc962.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_pressed.png", + "status": "generated", + "reference_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_button_normal.png" +} diff --git a/assets-source/phase3/records/ui_panel_a.json b/assets-source/phase3/records/ui_panel_a.json new file mode 100644 index 0000000..6796371 --- /dev/null +++ b/assets-source/phase3/records/ui_panel_a.json @@ -0,0 +1,12 @@ +{ + "id": "ui_panel_a", + "display_name": "Breiter UI-Rahmen", + "faction": "ui", + "kind": "ui_frame", + "description_de": "Breiter offener UI-Rahmen mit Basaltfassung, schmaler Messingkante und ruhigen, geraden Seiten.", + "prompt": "Create one production 2D UI FRAME PNG for original fantasy strategy game SAUMWACHT. Wide horizontal panel aspect ratio 3:1, frame fills 88% of canvas width. Absolutely straight-on orthographic view, no perspective. An EMPTY OPEN FRAME: both its entire inner rectangular window and the outside of the frame must be real alpha transparency. Render only the rim. Narrow matte basalt #292B35 outer frame, thin warm brass #D9A441 inner bevel, small geometric chamfered corner braces, tiny dark petrol #247A80 inlays; soft upper-left lighting in painted low-poly facets. Straight plain sides suitable for nine-patch stretching, corner decoration contained close to corners. Flat clean game asset, not photoreal. No center fill, no background, no text, no runes, no icons, no ground shadow, no watermark. Single isolated horizontal hollow panel, transparent center is essential.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-478f79e7-781f-4b3d-857a-7d8d7f4d1a13.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_panel_a.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/ui_panel_b.json b/assets-source/phase3/records/ui_panel_b.json new file mode 100644 index 0000000..c4b8cf6 --- /dev/null +++ b/assets-source/phase3/records/ui_panel_b.json @@ -0,0 +1,12 @@ +{ + "id": "ui_panel_b", + "display_name": "Hoher UI-Rahmen", + "faction": "ui", + "kind": "ui_frame", + "description_de": "Hoher offener UI-Rahmen für Einheiteninfos, mit Basaltfassung und geometrischen Messingecken.", + "prompt": "Create one production 2D UI FRAME PNG for original fantasy strategy game SAUMWACHT. Tall vertical panel aspect ratio 2:3, frame fills 88% of canvas height. Absolutely straight-on orthographic view, no perspective. An EMPTY OPEN FRAME: both its entire inner rectangular window and the outside of the frame must be real alpha transparency. Render only the rim. Narrow matte basalt #292B35 outer frame, thin warm brass #D9A441 inner bevel, small geometric chamfered corner braces, tiny dark petrol #247A80 inlays; soft upper-left lighting in painted low-poly facets. Straight plain sides suitable for nine-patch stretching, corner decoration contained close to corners. Flat clean game asset, not photoreal. No center fill, no background, no text, no runes, no icons, no ground shadow, no watermark. Single isolated vertical hollow panel, transparent center is essential.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a095b1-2da4-7bd1-9759-74ea0f1615bf/exec-94ebaa1d-3e9c-4021-9b94-c9cd89ec09e5.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/ui/ui_panel_b.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w01.json b/assets-source/phase3/records/w01.json new file mode 100644 index 0000000..efc341c --- /dev/null +++ b/assets-source/phase3/records/w01.json @@ -0,0 +1,12 @@ +{ + "id": "w01", + "display_name": "Dornhopser", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Kleine hüpfende Dornkapsel auf breiten Wurzelfüßen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Dornhopser: a small hopping round thorn-pod creature with stout root feet, compact brown seed-shell body, moss green triangular thorn blades, a tiny slit face, small paired leaf sprouts; inexpensive melee attacker. Root feet and thorn-pod silhouette are defining. No weapons, no human proportions.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-6fef6f8a-ddb9-4d61-8837-7fb775e26c14.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w02.json b/assets-source/phase3/records/w02.json new file mode 100644 index 0000000..57fdc7e --- /dev/null +++ b/assets-source/phase3/records/w02.json @@ -0,0 +1,12 @@ +{ + "id": "w02", + "display_name": "Rankenschnapper", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Breiter Rankenräuber mit großem Dornenmaul und Wurzelfüßen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Rankenschnapper: an upgraded robust vine-jaw predator, broad hinged plant maw with a few oversized sharp thorn fangs, thick coiled bark vines forming stocky mobile torso, four chunky root feet, broad green leaf cheek plates. Controlled fierce expression; silhouette dominated by the huge horizontal snapping jaw. No humanoid anatomy, no weapons.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-87dbb099-b6ea-4aef-8c18-844f0db03e04.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w03.json b/assets-source/phase3/records/w03.json new file mode 100644 index 0000000..0fc9ef3 --- /dev/null +++ b/assets-source/phase3/records/w03.json @@ -0,0 +1,12 @@ +{ + "id": "w03", + "display_name": "Korkrücken", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Gedrungener Tank mit breitem Korkpanzer, Moos und Wurzelfüßen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Korkrücken: a squat nonhumanoid wooden tank creature under an oversized shield-back of thick cork bark plates, four broad stubby root feet, very low head with tiny leaf-green eyes peeking under the front shell, rounded compact defensive silhouette. Bark brown dominates with moss green seams, a few large leaf plates. Entire creature easily fits the square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-63e0cc2b-e4d4-49ee-af0e-83ec417f05d9.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w04.json b/assets-source/phase3/records/w04.json new file mode 100644 index 0000000..8067578 --- /dev/null +++ b/assets-source/phase3/records/w04.json @@ -0,0 +1,12 @@ +{ + "id": "w04", + "display_name": "Ringborke", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Großer Wurzeltank mit konzentrischen Holzringen als massiver Panzerung.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Ringborke: a huge upgraded nonhumanoid wooden tank, massive overlapping circular trunk cross-section armor shields showing clear bold concentric wood growth rings, thick root limbs and flat wide root feet, small recessed leaf-green eyes, heavy shoulder and back bulk, tiny moss patches and few leaves. It is a mobile root organism, not a humanoid ent. Silhouette strongly broad and heavy; dominant readable wooden concentric circles. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-ce1833cd-62ce-42b7-a82f-9ef98887509e.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w05.json b/assets-source/phase3/records/w05.json new file mode 100644 index 0000000..030f553 --- /dev/null +++ b/assets-source/phase3/records/w05.json @@ -0,0 +1,12 @@ +{ + "id": "w05", + "display_name": "Samenschleuder", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Schlanker Wurzelfernkämpfer mit gebogener Ranke und offener Samenkapsel als Wurfschale.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Samenschleuder: a slender mobile seedpod catapult creature; three thin arched living root legs spread into broad root toes, flexible curved vine torso bent back like a spring, one large open green seedpod cup at its top holding one chunky brown seed ready to launch. Two leaf fins for balance, tiny slit eyes in the bark below the cup. Clear elegant narrow ranged-unit silhouette, entirely plant organism, no humanoid arms, no mechanical hardware. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-e837c72b-54e7-407d-8bf3-dae94faa4aac.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w06.json b/assets-source/phase3/records/w06.json new file mode 100644 index 0000000..f596230 --- /dev/null +++ b/assets-source/phase3/records/w06.json @@ -0,0 +1,12 @@ +{ + "id": "w06", + "display_name": "Zapfenkrone", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Hoher Samenschütze mit großer Zapfenkrone, kräftigen Ranken und Blattschalen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Zapfenkrone: tall upgraded seed-launching plant creature with an enormous crown-shaped pinecone launcher on top, several broad overlapping bark scales forming an upward open cone crown, one chunky seed visible within, green leaf collars, strong curved vine stem torso, three mobile root legs with broad toes. Silhouette much taller and statelier than a small seedpod catapult, all living wood and plants, tiny eyes below crown, never humanoid. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-9580ae74-e7fc-429f-8422-3c1dce830b15.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w07.json b/assets-source/phase3/records/w07.json new file mode 100644 index 0000000..a46a3a1 --- /dev/null +++ b/assets-source/phase3/records/w07.json @@ -0,0 +1,12 @@ +{ + "id": "w07", + "display_name": "Sporenkelch", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Niedriger offener Pilzkelch mit rosiger Sporenmulde und breiten Wurzelfüßen.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Sporenkelch: squat open mushroom-chalice creature, one huge concave cup fungus tilted enough to show its open spore bowl, dusty blossom pink inner cup with a few large pale seedlike spores resting inside, moss green outer lip, thick bark-clay stem body and four chunky root feet, tiny recessed eyes on stalk. Silhouette is unmistakably a broad open cup on a short rooted base, no humanoid anatomy. No drifting particles outside silhouette. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-6e164b57-339c-443c-ae29-09935cd1226e.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w08.json b/assets-source/phase3/records/w08.json new file mode 100644 index 0000000..60c46d2 --- /dev/null +++ b/assets-source/phase3/records/w08.json @@ -0,0 +1,12 @@ +{ + "id": "w08", + "display_name": "Pilzkathedrale", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Große mobile Pilzarchitektur mit gestaffelten rosigen Pilzdächern und massivem Wurzelwerk.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Pilzkathedrale: large upgraded mobile mushroom architecture creature, several broad stacked mushroom canopies arranged as a three-tier cathedral silhouette over one living bark and root body. Dusty blossom pink fungus caps and inner gills, moss green edges and leaf accents, heavy interwoven root buttresses and four broad mobile feet. Topmost cap forms an open spore cup; smaller side canopies step down symmetrically. Recognizable organic architectural silhouette, not an actual building, no windows or doors or stone masonry, no humans. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-f7f08c31-2ef2-41e1-8e89-5c63f9e6dd65.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w09.json b/assets-source/phase3/records/w09.json new file mode 100644 index 0000000..94336c2 --- /dev/null +++ b/assets-source/phase3/records/w09.json @@ -0,0 +1,12 @@ +{ + "id": "w09", + "display_name": "Tauhüter", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Kleiner Blatthüter mit einzelnem Tautropfen in einer schützenden Blattschale.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Tauhüter: small gentle nonhumanoid leaf healer, compact woven root body on three chunky root feet, two curved root tendrils supporting a single large cupped leaf in front of its body. The leaf holds exactly ONE oversized clear pale-mint dewdrop, the focal point. A simple three-leaf canopy on its back, tiny gentle green eyes beneath canopy. Rind brown and moss green dominate with one small pink blossom. No humanoid elf anatomy, no clothes, no staff. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-a9291f97-c46f-4902-a656-1f4d2537f23c.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/w10.json b/assets-source/phase3/records/w10.json new file mode 100644 index 0000000..65be6fd --- /dev/null +++ b/assets-source/phase3/records/w10.json @@ -0,0 +1,12 @@ +{ + "id": "w10", + "display_name": "Quellgeflecht", + "faction": "wurzelbund", + "kind": "unit_icon", + "description_de": "Großer Heiler aus verflochtenen Wurzeln mit Quellwasserschale unter einem Blüten- und Blätterdach.", + "prompt": "Use case: stylized-concept. Asset type: original fantasy strategy-game unit UI icon for Saumwacht, Wurzelbund faction. Style: faceted illustrated low-poly game art, broad flat matte planes, crisp silhouette and edges, chunky simple forms, high readability at 256px, not photorealistic, not a painting. Composition: ONE whole single creature centered, square canvas, complete feet and appendages visible, creature occupies 75-80% of canvas, generous transparent margins. 3/4 front view facing slightly right. Lighting: soft upper-left light, restrained shadows within subject. Palette: bark #685441, moss #56845A, leaf #A7BA6C, sparse blossom #D996AF accents. Scene: truly transparent alpha background, no checkerboard pixels, no ground plane, no scenery, no frame, no text, no logo, no watermark, no cast shadow. Wurzelbund creatures are mobile wood, root, leaf and clay organisms, never humanoid wood elves.\nSubject: Quellgeflecht: large upgraded mobile woven-root healer creature, a wide open bowl of clear pale-mint spring water cradled in interlaced chunky living roots at its chest, a broad layered leaf-and-blossom canopy arching above bowl, thick braided root body and four sturdy root feet. Gentle recessed eyes tucked below canopy, dusty pink flowers accenting green leaves. Water bowl must be conspicuous and readable. Entirely organic mobile plant organism, not humanoid, no clothing, no architecture, no floating water particles. Entire creature fits square with 12% transparent margin on EVERY side.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-120bac3c-d575-4331-a7e9-5812241f56a4.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png", + "status": "generated" +} diff --git a/assets-source/phase3/records/worker_funkenleser.json b/assets-source/phase3/records/worker_funkenleser.json new file mode 100644 index 0000000..4b1f08b --- /dev/null +++ b/assets-source/phase3/records/worker_funkenleser.json @@ -0,0 +1,12 @@ +{ + "id": "worker_funkenleser", + "display_name": "Funkenleser", + "faction": "neutral", + "kind": "worker_icon", + "description_de": "Kleine Lehmgestalt im Arbeitstuch mit gegabeltem Funkensammler und Glasbehälter.", + "prompt": "Use case: stylized-concept. Asset type: standalone resource UI icon for original fantasy strategy game Saumwacht. Faceted illustrated game UI art, large simple flat matte planes, crisp graphic edges, restrained shading, very clear shape readable at 48px and 256px. Single coherent centered icon on square canvas, whole object visible, occupies around 75% canvas with transparent margins all sides. Three-quarter front view facing slightly right, soft neutral upper-left key light. Palette warm brass gold #D9A441, pale mint teal #82DBCE, coral #E9967C, slate #536375. Truly transparent RGBA alpha background, no checkerboard pixels, no ground, no cast shadow, no border or frame, no badge background, no text, no letters, no numerals, no logos, no watermark. Avoid photorealism, glossy rendering and tiny texture.\nSubject: A whole single small neutral WORKER creature named Funkenleser, a squat original clay golem organism with a simple rounded faceted terracotta clay face and tiny inset eyes, short chunky clay feet, practical slate-colored cloth hood and apron with broad simple folds. It holds a forked brass spark-collector tool in one short clay hand, and a small clear glass container with one mint energy spark in its other hand. Tiny warm brass buckles, approachable industrious stance. No human skin, no pointed elf ears, no weapons, no writing. Entire worker and tool are fully visible, compact silhouette with 12% transparent margins all sides. Same matte faceted strategy-game art as resource icons.", + "generation_mode": "built-in", + "source_path": "/home/martin/.codex/generated_images/01a096fb-ea61-7671-8a5d-a14abb62467d/exec-143f6c4c-6567-4a09-b262-03535ac820e5.png", + "master_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase3/masters/neutral/worker_funkenleser_icon.png", + "status": "generated" +} diff --git a/assets-source/phase4/README.md b/assets-source/phase4/README.md new file mode 100644 index 0000000..9921e28 --- /dev/null +++ b/assets-source/phase4/README.md @@ -0,0 +1,168 @@ +# Saumwacht · Phase 4 · Blender-Modelle + +Die Lieferung enthält **59 GLB-Modelle und 59 bearbeitbare `.blend`-Dateien**: 40 Fraktionseinheiten, zehn Wellengegner, fünf Söldner, den Funkenleser, ein Lane-Segment und zwei Teamkerne. Glutpakt und Wellengegner verwenden seit Demo 0.7.0 die neue hochdetaillierte Quelle `blender/reference_high_detail.py`; das Dreiecksbudget dieser Modelle liegt bei 100.000. Neutrale Modelle und Umgebung erhielten zusätzliche Kantengeometrie. Die Farbwerte der neuen Glutpakt- und Gegnerpalette stehen in `hd_materials`; die unten beschriebenen `PALETTE_OVERRIDES` gelten für die ursprünglichen Paletten. + +Wellengegner werden mit `generate_all.py -- --faction rift` erzeugt; die neun Einzeldateien decken weiterhin die ursprünglichen Rollen ab. Details und aktuelle Prüfungen: [Grafikbericht](../../../docs/phase-07-hochdetaillierte-modelle.md). + +Alle Formen entstehen aus den beigefügten parametrischen Blender-Skripten. Materialien und benannte Einzelteile werden mit exportiert. + +**Revision vom 15. September 2026:** Alle 46 Figuren wurden anhand der Icons aus Phase 3 neu aufgebaut. Die [Vergleichsgalerie](../../docs/screenshots/phase4/reference-gallery.html) zeigt die unveränderten Originalbilder direkt neben aktuellen Godot-Renderings. Körperbau, Konturen und Hauptmotive wurden korrigiert; kleine Verzierungen, Oberflächen und Rundungen bleiben vereinfacht. Basis und Upgrade unterscheiden sich durch zusätzliche oder veränderte Geometrie, etwa Klauen, Zinnen, Klingen, Kessel, Schilde oder Holzringe. Die Spielintegration folgt in Phase 5. + +Phase 6 ergänzt beim Glutpakt Basalt-/Goldfacetten und ein verfeinertes Schildrelief; GLBs, native Szenen und eigenständige Skripte sind aktualisiert. Die Gelenkanimationen entstehen im Godot-Spiel aus den benannten Teilen. + +## Dateien finden + +| Inhalt | Ort, relativ zum Godot-Projekt | +| --- | --- | +| 59 fertige GLB-Dateien | `assets/models/` | +| 59 bearbeitbare Blender-Dateien | `assets-source/phase4/blend/` | +| Neun eigenständige Skripte | `assets-source/phase4/standalone/` | +| Modulare Generatorquellen und Batch-Export | `assets-source/phase4/blender/` | +| Modellmetadaten und Maße | `assets/phase4_manifest.json` | +| Einzeldatensätze der Exporte | `assets-source/phase4/records/` | +| Eigenständige Godot-Vorschau | `tools/model_gallery.tscn` | + +Der [Modellkatalog](catalog.md) führt alle 59 Modelle mit Rollen, Upgrade-Status, Dreieckszahlen und Maßen auf. Jeder Eintrag verlinkt die GLB-Datei. + +## Ein Modell in Blender erzeugen + +1. Blender öffnen und zum Arbeitsbereich **Scripting** wechseln. +2. Im Texteditor **Text → Open** wählen und eines der Skripte aus `standalone/` öffnen, beispielsweise `create_melee.py`. +3. Im Parameterblock oben `ASSET_ID` auf die gewünschte Variante setzen, beispielsweise `"w02"`. +4. **Run Script** beziehungsweise **Alt+P** ausführen. +5. Blender zeigt die neue Szene `Saumwacht_`. Die GLB-Datei und die bearbeitbare `.blend`-Datei werden automatisch geschrieben. + +Jedes Skript ist eigenständig: Es benötigt Blender mit `bpy`, aber keine benachbarten Python-Module oder JSON-Dateien. Im Projekt liegen die Standardausgaben unter `assets/models/` und `assets-source/phase4/blend/`. Wird ein Skript separat in einen anderen Ordner kopiert, verwendet es daneben `saumwacht-export/` und `saumwacht-source/blend/`. + +**Vorhandene eigene Szenen bleiben erhalten.** Der Generator erstellt eine neue Szene und exportiert deren Modell. Mit `KEEP_SCENE = True` bleibt diese neue Szene aktiv. Mit `False` wird nach dem Export zur vorherigen Szene zurückgekehrt und nur die temporär erzeugte Szene entfernt. Die `.blend`-Ausgabe enthält die erzeugte Szene mit ihren Abhängigkeiten. + +Ein erneuter Lauf derselben ID schreibt deren GLB- und `.blend`-Ausgaben neu. Für eigene Varianten können getrennte Ausgabeordner gesetzt werden. + +## Skripte und verfügbare IDs + +Die folgenden IDs stammen aus den tatsächlich enthaltenen `ASSET_SPECS` der neun Skripte. + +| Skript | Klasse | Verfügbare IDs | +| --- | --- | --- | +| [create_melee.py](standalone/create_melee.py) | Nahkampf | `g01`, `g02`, `m03`, `m04`, `n03`, `n04`, `w01`, `w02` | +| [create_tank.py](standalone/create_tank.py) | Tank | `g03`, `g04`, `m01`, `m02`, `n01`, `n02`, `w03`, `w04` | +| [create_ranged.py](standalone/create_ranged.py) | Fernkampf | `g05`, `g06`, `m05`, `m06`, `n05`, `n06`, `w05`, `w06` | +| [create_artillery.py](standalone/create_artillery.py) | Artillerie | `g07`, `g08`, `m07`, `m08`, `n07`, `n08`, `w07`, `w08` | +| [create_support.py](standalone/create_support.py) | Unterstützung | `g09`, `g10`, `m09`, `m10`, `n09`, `n10`, `w09`, `w10` | +| [create_mercenary.py](standalone/create_mercenary.py) | Söldner | `s01`, `s02`, `s03`, `s04`, `s05` | +| [create_worker.py](standalone/create_worker.py) | Arbeiter | `worker` | +| [create_lane.py](standalone/create_lane.py) | Lane-Segment | `map_lane_segment` | +| [create_core.py](standalone/create_core.py) | Saumkern | `core_team0`, `core_team1` | + +Bei den vier Fraktionen bilden die aufeinanderfolgenden ungeraden und geraden IDs jeweils Basis und Upgrade. Für Söldner, Arbeiter, Lane und Kerne gibt es keine Upgrade-Paare. `core_team0` und `core_team1` sind Teamvarianten. + +## Parameter anpassen + +| Parameter | Wirkung | +| --- | --- | +| `ASSET_ID` | Wählt eine der oben aufgeführten Varianten des geöffneten Skripts. | +| `HEIGHT` | `None` verwendet das Katalogmaß; eine positive Zahl gibt eine Zielhöhe in Metern vor. Der maximale Zell-Footprint kann die tatsächliche Höhe begrenzen. Das Lane-Segment behält seine festen Modulmaße. | +| `PALETTE_OVERRIDES` | Ersetzt einzelne Materialfarben mit RGB-Hexwerten, etwa `{"accent": "D9A441"}`. Schlüssel: `primary`, `secondary`, `accent`, `light`; beim Wurzelbund zusätzlich `water`, `wood`, `bark_dark`, bei Neutral/Arbeiter `shadow` und bei Neutral `rift`. Nicht angegebene Farben bleiben beim Fraktionsstandard. | +| `EXPORT_DIR` | `None` verwendet den Standardordner für GLB-Dateien; alternativ einen eigenen absoluten Ordnerpfad angeben. | +| `BLEND_DIR` | `None` verwendet den Standardordner für `.blend`-Dateien; alternativ einen eigenen absoluten Ordnerpfad angeben. | +| `KEEP_SCENE` | `True` lässt das Ergebnis in Blender sichtbar; `False` kehrt nach dem Export zur vorherigen Szene zurück. | + +Beispiel für eine veränderte Nahkampfeinheit: + +```python +ASSET_ID = "g02" +HEIGHT = 1.60 +PALETTE_OVERRIDES = {"accent": "D9A441", "secondary": "F27B43"} +EXPORT_DIR = "/tmp/saumwacht-varianten/models" +BLEND_DIR = "/tmp/saumwacht-varianten/blend" +KEEP_SCENE = True +``` + +Für Formänderungen stehen darunter kleine Funktionen für Körper, Beine, Kopf, Waffen und Zubehör bereit. Die eigenständigen Skripte sind aus den modularen Quellen generierte, vollständig eingebettete Fassungen. Die Figurenformen stehen in `blender/reference_glutpakt.py`, `reference_nietenkonvent.py`, `reference_nebelchor.py`, `reference_wurzelbund.py` und `reference_neutral.py`; gemeinsame Formwerkzeuge in `reference_geometry.py`. Projektweite Änderungen werden in `blender/` gepflegt; `tools/build_standalone_model_scripts.py` aktualisiert anschließend die Fassungen in `standalone/`. + +## Export über die Kommandozeile + +Die folgenden Befehle im Ordner `saumwacht-godot/` ausführen. `ALSOFT_DRIVERS=null` deaktiviert für den unbeaufsichtigten Blender-Lauf die Audioausgabe. `--factory-startup` gilt für den dafür gestarteten Hintergrundprozess. + +Alle 59 Modelle samt Manifest neu erzeugen: + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup \ + --python assets-source/phase4/blender/generate_all.py -- --all +``` + +Zwei bestimmte IDs aus den modularen Quellen exportieren: + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup \ + --python assets-source/phase4/blender/generate_all.py -- --id g01 --id g02 +``` + +Alle Tanks in getrennte Ausgabeordner exportieren: + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup \ + --python assets-source/phase4/blender/generate_all.py -- --role tank \ + --export-dir /tmp/saumwacht-tanks/models \ + --blend-dir /tmp/saumwacht-tanks/blend +``` + +Ein einzelnes eigenständiges Skript mit Variantenwahl und Zielhöhe starten: + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup \ + --python assets-source/phase4/standalone/create_melee.py -- \ + --id w02 --height 1.6 --no-keep-scene \ + --export-dir /tmp/saumwacht-varianten/models \ + --blend-dir /tmp/saumwacht-varianten/blend +``` + +Die Skripte unterstützen außerdem die im Parameterblock gesetzten Standardwerte. Farbänderungen werden dort über `PALETTE_OVERRIDES` vorgenommen. Der vollständige Batch-Lauf schreibt das gemeinsame Manifest neu; ein einzelner Variantenexport aktualisiert nur seinen eigenen Datensatz. Nach Teil-Exporten in die offiziellen Ausgabeordner lässt sich das Manifest aus den aktuellen Datensätzen aktualisieren, ohne die angepassten Modelle neu zu erzeugen: + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup --python-exit-code 1 \ + --python-expr "import sys; sys.path.insert(0, 'assets-source/phase4/blender'); from pipeline import write_manifest; write_manifest()" +``` + +Ein neuer vollständiger Batch-Lauf verwendet wieder die modularen Quellen und deren Katalogwerte. Anpassungen ausschließlich in einem Einzelskript oder einer `.blend`-Datei werden dadurch überschrieben. Der Markdown-Katalog ist eine Momentaufnahme der Lieferung; aktuelle Maße stehen nach einem neuen Export im Manifest. + +## Modelle in Godot ansehen + +Godot importiert die GLB-Dateien beim Öffnen des Projekts. Danach `tools/model_gallery.tscn` öffnen und mit **F6** starten. Alternativ aus dem Godot-Projektordner: + +```bash +godot --path . res://tools/model_gallery.tscn +``` + +Die Galerie bietet Fraktions- und Modellauswahl, Maße und Dreieckszahlen sowie die zugehörige Iconreferenz. Ziehen dreht das Modell, das Mausrad ändert den Zoom; die automatische Drehung lässt sich zuschalten. Alle Modelle werden proportional auf eine gemeinsame Vorschaubühne eingepasst. + +Die Kontaktbögen mit echter Godot-Beleuchtung entstehen nach abgeschlossenem Import über: + +```bash +godot --path . res://tools/model_gallery.tscn -- --capture +``` + +Direkte Bildvergleiche entstehen mit `-- --compare --faction=nebelchor` (auch `glutpakt`, `nietenkonvent`, `wurzelbund`, `neutral`). Nach dem Rendern aller fünf Gruppen aktualisiert `python3 tools/build_phase4_reference_gallery.py` die lokale HTML-Galerie und den Katalog. Die Vergleichsszene liest die nativen PNGs direkt und ist für die lokale Entwicklungsumgebung vorgesehen. + +Die Aufnahmen werden unter `docs/screenshots/phase4/` gespeichert. Dafür ist ein grafischer Godot-Lauf erforderlich. + +## Maße und Weiterverwendung + +Eine Einheit entspricht einem Meter. Blender verwendet **+Z oben und −Y vorne**; die GLB-Dateien verwenden in Godot **+Y oben und +Z vorne**. Einheiten stehen mit ihrem Ursprung auf dem Boden. Beim Lane-Segment liegt die begehbare Oberkante bei Y = 0. + +Die Modelle bestehen aus benannten Einzelteilen und matten Materialien. Sie enthalten keine externen Texturen, Kameras, Lichtquellen oder Animationsclips. Die Vorschau fügt ihre eigene Bühne, Kamera und Beleuchtung hinzu. Die vollständigen Exportmaße stehen im Manifest als `bounds_godot`; B/H/T im Katalog sind die daraus berechneten Ausdehnungen entlang X/Y/Z. + +**Geprüft mit Blender 5.2.1 LTS und Godot 4.7.2:** 59/59 GLB-Dateien, 59/59 Godot-Imports und alle neun in einen unabhängigen Ordner kopierten Einzelskripte. Weitere Ergebnisse und die sieben gerenderten Modellübersichten stehen im [Liefer- und Prüfbericht](../../../docs/phase-04-3d-pipeline.md). + +Die vorige Modellfassung liegt reproduzierbar in `revisions/before-icon-match.tar.gz`. Die Originalicons wurden für die Korrektur nicht geändert. + +### Phase 9 · Lebende Formen und Basis + +`blender/reference_living_detail.py` erstellt alle zehn Wurzelbund-Figuren sowie Arbeiter und beide Kristalle neu. Blätter sind geschlossene Körper mit modellierten Adern; Wurzeln, Borke, Jahresringe, Kelche, Mineralspitzen und Arbeitsgeräte besitzen eigene benannte Teile. `LegL`, `LegR` und zusätzliche Wurzelgruppen sind Animationsgelenke; `Core_Crystal*` bildet die schwebende Mineralgruppe. Die Palette verwendet eigene Materialnamen `SW_HD_W_*`, damit Glutpakt-Materialien nicht überschrieben werden. + +```bash +ALSOFT_DRIVERS=null blender --background --factory-startup --python-exit-code 1 --python blender/generate_all.py -- --faction wurzelbund +ALSOFT_DRIVERS=null blender --background --factory-startup --python-exit-code 1 --python blender/generate_all.py -- --id worker --id core_team0 --id core_team1 +``` + +Nach einzelnen Exporten den gemeinsamen Manifest-Schritt ausführen und die eigenständigen Skripte über `../../tools/build_standalone_model_scripts.py` neu bündeln (Pfad vom Projektwurzelverzeichnis: `tools/build_standalone_model_scripts.py`). Die tatsächlichen Dreieckszahlen stehen in `assets/phase4_manifest.json`. Höchstens 100.000 Dreiecke pro neuem Modell; die Topologieprüfung wird unverändert angewendet. diff --git a/assets-source/phase4/blend/core_team0.blend b/assets-source/phase4/blend/core_team0.blend new file mode 100644 index 0000000..3d4ab64 Binary files /dev/null and b/assets-source/phase4/blend/core_team0.blend differ diff --git a/assets-source/phase4/blend/core_team1.blend b/assets-source/phase4/blend/core_team1.blend new file mode 100644 index 0000000..3e10b4f Binary files /dev/null and b/assets-source/phase4/blend/core_team1.blend differ diff --git a/assets-source/phase4/blend/e01.blend b/assets-source/phase4/blend/e01.blend new file mode 100644 index 0000000..868d44b Binary files /dev/null and b/assets-source/phase4/blend/e01.blend differ diff --git a/assets-source/phase4/blend/e02.blend b/assets-source/phase4/blend/e02.blend new file mode 100644 index 0000000..616fe25 Binary files /dev/null and b/assets-source/phase4/blend/e02.blend differ diff --git a/assets-source/phase4/blend/e03.blend b/assets-source/phase4/blend/e03.blend new file mode 100644 index 0000000..c811aef Binary files /dev/null and b/assets-source/phase4/blend/e03.blend differ diff --git a/assets-source/phase4/blend/e04.blend b/assets-source/phase4/blend/e04.blend new file mode 100644 index 0000000..9442488 Binary files /dev/null and b/assets-source/phase4/blend/e04.blend differ diff --git a/assets-source/phase4/blend/e05.blend b/assets-source/phase4/blend/e05.blend new file mode 100644 index 0000000..8bf6b66 Binary files /dev/null and b/assets-source/phase4/blend/e05.blend differ diff --git a/assets-source/phase4/blend/e06.blend b/assets-source/phase4/blend/e06.blend new file mode 100644 index 0000000..ccade5a Binary files /dev/null and b/assets-source/phase4/blend/e06.blend differ diff --git a/assets-source/phase4/blend/e07.blend b/assets-source/phase4/blend/e07.blend new file mode 100644 index 0000000..5073394 Binary files /dev/null and b/assets-source/phase4/blend/e07.blend differ diff --git a/assets-source/phase4/blend/e08.blend b/assets-source/phase4/blend/e08.blend new file mode 100644 index 0000000..2a89b29 Binary files /dev/null and b/assets-source/phase4/blend/e08.blend differ diff --git a/assets-source/phase4/blend/e09.blend b/assets-source/phase4/blend/e09.blend new file mode 100644 index 0000000..a7b34f7 Binary files /dev/null and b/assets-source/phase4/blend/e09.blend differ diff --git a/assets-source/phase4/blend/e10.blend b/assets-source/phase4/blend/e10.blend new file mode 100644 index 0000000..d2fe695 Binary files /dev/null and b/assets-source/phase4/blend/e10.blend differ diff --git a/assets-source/phase4/blend/g01.blend b/assets-source/phase4/blend/g01.blend new file mode 100644 index 0000000..a7664b3 Binary files /dev/null and b/assets-source/phase4/blend/g01.blend differ diff --git a/assets-source/phase4/blend/g02.blend b/assets-source/phase4/blend/g02.blend new file mode 100644 index 0000000..db3efa1 Binary files /dev/null and b/assets-source/phase4/blend/g02.blend differ diff --git a/assets-source/phase4/blend/g03.blend b/assets-source/phase4/blend/g03.blend new file mode 100644 index 0000000..2476d45 Binary files /dev/null and b/assets-source/phase4/blend/g03.blend differ diff --git a/assets-source/phase4/blend/g04.blend b/assets-source/phase4/blend/g04.blend new file mode 100644 index 0000000..81b0a07 Binary files /dev/null and b/assets-source/phase4/blend/g04.blend differ diff --git a/assets-source/phase4/blend/g05.blend b/assets-source/phase4/blend/g05.blend new file mode 100644 index 0000000..01bd3e7 Binary files /dev/null and b/assets-source/phase4/blend/g05.blend differ diff --git a/assets-source/phase4/blend/g06.blend b/assets-source/phase4/blend/g06.blend new file mode 100644 index 0000000..9d28345 Binary files /dev/null and b/assets-source/phase4/blend/g06.blend differ diff --git a/assets-source/phase4/blend/g07.blend b/assets-source/phase4/blend/g07.blend new file mode 100644 index 0000000..4b3e551 Binary files /dev/null and b/assets-source/phase4/blend/g07.blend differ diff --git a/assets-source/phase4/blend/g08.blend b/assets-source/phase4/blend/g08.blend new file mode 100644 index 0000000..a4d1e20 Binary files /dev/null and b/assets-source/phase4/blend/g08.blend differ diff --git a/assets-source/phase4/blend/g09.blend b/assets-source/phase4/blend/g09.blend new file mode 100644 index 0000000..eec005b Binary files /dev/null and b/assets-source/phase4/blend/g09.blend differ diff --git a/assets-source/phase4/blend/g10.blend b/assets-source/phase4/blend/g10.blend new file mode 100644 index 0000000..0aa2820 Binary files /dev/null and b/assets-source/phase4/blend/g10.blend differ diff --git a/assets-source/phase4/blend/m01.blend b/assets-source/phase4/blend/m01.blend new file mode 100644 index 0000000..dd7d333 Binary files /dev/null and b/assets-source/phase4/blend/m01.blend differ diff --git a/assets-source/phase4/blend/m02.blend b/assets-source/phase4/blend/m02.blend new file mode 100644 index 0000000..35ff936 Binary files /dev/null and b/assets-source/phase4/blend/m02.blend differ diff --git a/assets-source/phase4/blend/m03.blend b/assets-source/phase4/blend/m03.blend new file mode 100644 index 0000000..aadd904 Binary files /dev/null and b/assets-source/phase4/blend/m03.blend differ diff --git a/assets-source/phase4/blend/m04.blend b/assets-source/phase4/blend/m04.blend new file mode 100644 index 0000000..04bf0cf Binary files /dev/null and b/assets-source/phase4/blend/m04.blend differ diff --git a/assets-source/phase4/blend/m05.blend b/assets-source/phase4/blend/m05.blend new file mode 100644 index 0000000..978c4ac Binary files /dev/null and b/assets-source/phase4/blend/m05.blend differ diff --git a/assets-source/phase4/blend/m06.blend b/assets-source/phase4/blend/m06.blend new file mode 100644 index 0000000..b96d3be Binary files /dev/null and b/assets-source/phase4/blend/m06.blend differ diff --git a/assets-source/phase4/blend/m07.blend b/assets-source/phase4/blend/m07.blend new file mode 100644 index 0000000..ec52319 Binary files /dev/null and b/assets-source/phase4/blend/m07.blend differ diff --git a/assets-source/phase4/blend/m08.blend b/assets-source/phase4/blend/m08.blend new file mode 100644 index 0000000..ef6dfdf Binary files /dev/null and b/assets-source/phase4/blend/m08.blend differ diff --git a/assets-source/phase4/blend/m09.blend b/assets-source/phase4/blend/m09.blend new file mode 100644 index 0000000..509ee63 Binary files /dev/null and b/assets-source/phase4/blend/m09.blend differ diff --git a/assets-source/phase4/blend/m10.blend b/assets-source/phase4/blend/m10.blend new file mode 100644 index 0000000..fa108a1 Binary files /dev/null and b/assets-source/phase4/blend/m10.blend differ diff --git a/assets-source/phase4/blend/map_lane_segment.blend b/assets-source/phase4/blend/map_lane_segment.blend new file mode 100644 index 0000000..a372132 Binary files /dev/null and b/assets-source/phase4/blend/map_lane_segment.blend differ diff --git a/assets-source/phase4/blend/n01.blend b/assets-source/phase4/blend/n01.blend new file mode 100644 index 0000000..fa81bdc Binary files /dev/null and b/assets-source/phase4/blend/n01.blend differ diff --git a/assets-source/phase4/blend/n02.blend b/assets-source/phase4/blend/n02.blend new file mode 100644 index 0000000..2492fbd Binary files /dev/null and b/assets-source/phase4/blend/n02.blend differ diff --git a/assets-source/phase4/blend/n03.blend b/assets-source/phase4/blend/n03.blend new file mode 100644 index 0000000..cea133b Binary files /dev/null and b/assets-source/phase4/blend/n03.blend differ diff --git a/assets-source/phase4/blend/n04.blend b/assets-source/phase4/blend/n04.blend new file mode 100644 index 0000000..807f22a Binary files /dev/null and b/assets-source/phase4/blend/n04.blend differ diff --git a/assets-source/phase4/blend/n05.blend b/assets-source/phase4/blend/n05.blend new file mode 100644 index 0000000..b629c3f Binary files /dev/null and b/assets-source/phase4/blend/n05.blend differ diff --git a/assets-source/phase4/blend/n06.blend b/assets-source/phase4/blend/n06.blend new file mode 100644 index 0000000..ca618c7 Binary files /dev/null and b/assets-source/phase4/blend/n06.blend differ diff --git a/assets-source/phase4/blend/n07.blend b/assets-source/phase4/blend/n07.blend new file mode 100644 index 0000000..321bbaf Binary files /dev/null and b/assets-source/phase4/blend/n07.blend differ diff --git a/assets-source/phase4/blend/n08.blend b/assets-source/phase4/blend/n08.blend new file mode 100644 index 0000000..f756504 Binary files /dev/null and b/assets-source/phase4/blend/n08.blend differ diff --git a/assets-source/phase4/blend/n09.blend b/assets-source/phase4/blend/n09.blend new file mode 100644 index 0000000..9356514 Binary files /dev/null and b/assets-source/phase4/blend/n09.blend differ diff --git a/assets-source/phase4/blend/n10.blend b/assets-source/phase4/blend/n10.blend new file mode 100644 index 0000000..cdf7b46 Binary files /dev/null and b/assets-source/phase4/blend/n10.blend differ diff --git a/assets-source/phase4/blend/s01.blend b/assets-source/phase4/blend/s01.blend new file mode 100644 index 0000000..1e7e417 Binary files /dev/null and b/assets-source/phase4/blend/s01.blend differ diff --git a/assets-source/phase4/blend/s02.blend b/assets-source/phase4/blend/s02.blend new file mode 100644 index 0000000..8d80ecf Binary files /dev/null and b/assets-source/phase4/blend/s02.blend differ diff --git a/assets-source/phase4/blend/s03.blend b/assets-source/phase4/blend/s03.blend new file mode 100644 index 0000000..9d8b8fa Binary files /dev/null and b/assets-source/phase4/blend/s03.blend differ diff --git a/assets-source/phase4/blend/s04.blend b/assets-source/phase4/blend/s04.blend new file mode 100644 index 0000000..05ed564 Binary files /dev/null and b/assets-source/phase4/blend/s04.blend differ diff --git a/assets-source/phase4/blend/s05.blend b/assets-source/phase4/blend/s05.blend new file mode 100644 index 0000000..220035e Binary files /dev/null and b/assets-source/phase4/blend/s05.blend differ diff --git a/assets-source/phase4/blend/w01.blend b/assets-source/phase4/blend/w01.blend new file mode 100644 index 0000000..08fef56 Binary files /dev/null and b/assets-source/phase4/blend/w01.blend differ diff --git a/assets-source/phase4/blend/w02.blend b/assets-source/phase4/blend/w02.blend new file mode 100644 index 0000000..82a1b61 Binary files /dev/null and b/assets-source/phase4/blend/w02.blend differ diff --git a/assets-source/phase4/blend/w03.blend b/assets-source/phase4/blend/w03.blend new file mode 100644 index 0000000..aa99edc Binary files /dev/null and b/assets-source/phase4/blend/w03.blend differ diff --git a/assets-source/phase4/blend/w04.blend b/assets-source/phase4/blend/w04.blend new file mode 100644 index 0000000..91d376d Binary files /dev/null and b/assets-source/phase4/blend/w04.blend differ diff --git a/assets-source/phase4/blend/w05.blend b/assets-source/phase4/blend/w05.blend new file mode 100644 index 0000000..beade1f Binary files /dev/null and b/assets-source/phase4/blend/w05.blend differ diff --git a/assets-source/phase4/blend/w06.blend b/assets-source/phase4/blend/w06.blend new file mode 100644 index 0000000..27ed377 Binary files /dev/null and b/assets-source/phase4/blend/w06.blend differ diff --git a/assets-source/phase4/blend/w07.blend b/assets-source/phase4/blend/w07.blend new file mode 100644 index 0000000..e296ec5 Binary files /dev/null and b/assets-source/phase4/blend/w07.blend differ diff --git a/assets-source/phase4/blend/w08.blend b/assets-source/phase4/blend/w08.blend new file mode 100644 index 0000000..ba12814 Binary files /dev/null and b/assets-source/phase4/blend/w08.blend differ diff --git a/assets-source/phase4/blend/w09.blend b/assets-source/phase4/blend/w09.blend new file mode 100644 index 0000000..859667c Binary files /dev/null and b/assets-source/phase4/blend/w09.blend differ diff --git a/assets-source/phase4/blend/w10.blend b/assets-source/phase4/blend/w10.blend new file mode 100644 index 0000000..6040ebf Binary files /dev/null and b/assets-source/phase4/blend/w10.blend differ diff --git a/assets-source/phase4/blend/worker.blend b/assets-source/phase4/blend/worker.blend new file mode 100644 index 0000000..1ced812 Binary files /dev/null and b/assets-source/phase4/blend/worker.blend differ diff --git a/assets-source/phase4/blender/__pycache__/backline.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/backline.cpython-314.pyc new file mode 100644 index 0000000..5a7489e Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/backline.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/catalog.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/catalog.cpython-314.pyc new file mode 100644 index 0000000..1d98ec2 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/catalog.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/common.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/common.cpython-314.pyc new file mode 100644 index 0000000..29ef88b Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/common.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/environment.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/environment.cpython-314.pyc new file mode 100644 index 0000000..e14efe4 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/environment.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/frontline.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/frontline.cpython-314.pyc new file mode 100644 index 0000000..73a5f6f Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/frontline.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/generate_all.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/generate_all.cpython-314.pyc new file mode 100644 index 0000000..c73c6e4 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/generate_all.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/pipeline.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/pipeline.cpython-314.pyc new file mode 100644 index 0000000..513642f Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/pipeline.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_geometry.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_geometry.cpython-314.pyc new file mode 100644 index 0000000..888cc19 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_geometry.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_glutpakt.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_glutpakt.cpython-314.pyc new file mode 100644 index 0000000..76f0043 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_glutpakt.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_high_detail.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_high_detail.cpython-314.pyc new file mode 100644 index 0000000..74480fc Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_high_detail.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_living_detail.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_living_detail.cpython-314.pyc new file mode 100644 index 0000000..7d148d8 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_living_detail.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_nebelchor.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_nebelchor.cpython-314.pyc new file mode 100644 index 0000000..b47242e Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_nebelchor.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_neutral.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_neutral.cpython-314.pyc new file mode 100644 index 0000000..1c55438 Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_neutral.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_nietenkonvent.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_nietenkonvent.cpython-314.pyc new file mode 100644 index 0000000..18a20bd Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_nietenkonvent.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_sculpt_detail.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_sculpt_detail.cpython-314.pyc new file mode 100644 index 0000000..4e8f03b Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_sculpt_detail.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/__pycache__/reference_wurzelbund.cpython-314.pyc b/assets-source/phase4/blender/__pycache__/reference_wurzelbund.cpython-314.pyc new file mode 100644 index 0000000..c64600e Binary files /dev/null and b/assets-source/phase4/blender/__pycache__/reference_wurzelbund.cpython-314.pyc differ diff --git a/assets-source/phase4/blender/backline.py b/assets-source/phase4/blender/backline.py new file mode 100644 index 0000000..24aa582 --- /dev/null +++ b/assets-source/phase4/blender/backline.py @@ -0,0 +1,570 @@ +"""Saumwacht backline: 24 faceted ranged, artillery and support variants. + +Coordinates are metres, Z up, face toward -Y. The exporter normalizes the +roughly 1.4 m figures to each catalog height. Every component stays separate +for object animation. No scene reset, export or material ownership lives here. +""" + +from math import cos, sin, pi, sqrt + +from common import box, ellipsoid, cylinder, cone, beam, ring, mesh_object, empty + + +def _add(a, b): + return tuple(a[i] + b[i] for i in range(3)) + + +def _mul(a, scale): + return tuple(v * scale for v in a) + + +def _cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def _unit(a): + length = sqrt(sum(v * v for v in a)) + return tuple(v / length for v in a) + + +def _frame(axis): + w = _unit(axis) + reference = (0, 0, 1) if abs(w[2]) < .9 else (0, 1, 0) + u = _unit(_cross(reference, w)) + return u, _cross(w, u), w + + +def _lathe(name, loc, profile, mat, axis=(0, 0, 1), segments=10): + """Closed profile, including real inner walls; zero radii become poles. + + Profile travels from the back/bottom up the outside, down the inside. + Independent pole vertices avoid degenerate zero-area triangles. + """ + u, v, w = _frame(axis) + verts, loops, faces = [], [], [] + for radius, depth in profile: + if radius == 0: + loops.append([len(verts)]) + verts.append(_add(loc, _mul(w, depth))) + continue + loop = [] + for k in range(segments): + angle = 2 * pi * k / segments + offset = _add(_mul(w, depth), + _add(_mul(u, radius * cos(angle)), + _mul(v, radius * sin(angle)))) + loop.append(len(verts)) + verts.append(_add(loc, offset)) + loops.append(loop) + for j in range(len(loops)): + low, high = loops[j], loops[(j + 1) % len(loops)] + if len(low) == 1 and len(high) == 1: + continue + for k in range(segments): + nxt = (k + 1) % segments + if len(low) == 1: + faces.append((low[0], high[nxt], high[k])) + elif len(high) == 1: + faces.append((low[k], low[nxt], high[0])) + else: + faces.append((low[k], low[nxt], high[nxt], high[k])) + mesh_object(name, verts, faces, mat) + + +def _cup(name, loc, radius, depth, mat, axis=(0, 0, 1), segments=10): + # The rim is 13% thick; the inset bottom is visible from above/front. + _lathe(name, loc, [(0, 0), (radius * .5, .04), + (radius * .73, depth * .35), (radius, depth), + (radius * .87, depth), (radius * .59, depth * .35), + (0, depth * .20)], mat, axis, segments) + + +def _horn(name, loc, radius, depth, mat, axis=(0, -1, .18)): + _lathe(name, loc, [(radius * .16, 0), (radius * .25, depth * .42), + (radius * .58, depth * .76), (radius, depth), + (radius * .84, depth), (radius * .43, depth * .72), + (radius * .1, depth * .35), (0, depth * .29), + (0, 0)], mat, axis, 10) + + +def _spike(name, start, end, radius, mat, sides=5): + axis = tuple(end[i] - start[i] for i in range(3)) + u, v, _ = _frame(axis) + verts = [_add(start, _add(_mul(u, radius * cos(2 * pi * k / sides)), + _mul(v, radius * sin(2 * pi * k / sides)))) + for k in range(sides)] + verts.append(end) + faces = [tuple(reversed(range(sides)))] + faces.extend((k, (k + 1) % sides, sides) for k in range(sides)) + mesh_object(name, verts, faces, mat) + + +def _leaf(name, loc, width, height, mat, lean=0): + # Thick diamond leaf: large central ridge, only eight triangles. + x, y, z = loc + verts = [(x, y, z), (x - width / 2, y, z + height * .42), + (x + lean, y + .05, z + height), + (x + width / 2, y, z + height * .42), + (x + lean * .3, y - .09, z + height * .45), + (x + lean * .3, y + .055, z + height * .45)] + faces = [(0, 4, 1), (1, 4, 2), (2, 4, 3), (3, 4, 0), + (1, 5, 0), (2, 5, 1), (3, 5, 2), (0, 5, 3)] + mesh_object(name, verts, faces, mat) + + +def _eyes(loc, mat, spread=.075, scale=.038): + for side, suffix in ((-1, "L"), (1, "R")): + p = (loc[0] + side * spread, loc[1], loc[2]) + ellipsoid("Head_Eye" + suffix, p, (scale, .023, scale * .75), mat) + + +def _mask(name, loc, scale, mat, eyes_mat): + ellipsoid(name, loc, (.15 * scale, .075 * scale, .22 * scale), mat) + for sign, suffix in ((-1, "L"), (1, "R")): + ellipsoid(name + "_Eye" + suffix, + (loc[0] + sign * .052 * scale, loc[1] - .071 * scale, + loc[2] + .023 * scale), + (.028 * scale, .012 * scale, .046 * scale), eyes_mat) + + +def _basalt_legs(mat, wide=False): + spread = .32 if wide else .22 + for side, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Leg" + suffix + "_Foot", (side * spread, -.075, .12), + (.20 if wide else .15, .24, .12), mat) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .15), + (side * spread * .7, .02, .49), .095, mat, vertices=6) + + +def _mechanical_legs(mat, wide=False): + spread = .27 if wide else .20 + for side, suffix in ((-1, "L"), (1, "R")): + box("Leg" + suffix + "_Foot", (side * spread, -.07, .07), + (.22, .33, .14), mat["accent"]) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .14), + (side * spread, .08, .35), .065, mat["accent"], vertices=6) + ellipsoid("Leg" + suffix + "_Knee", (side * spread, .08, .35), + (.10, .10, .10), mat["secondary"]) + beam("Leg" + suffix + "_Thigh", (side * spread, .08, .35), + (side * spread * .66, 0, .57), .09, mat["primary"], vertices=6) + + +def _root_feet(mat, count=4, spread=.43, top=.60): + for k in range(count): + a = 2 * pi * k / count + pi / 4 + base = (spread * cos(a), spread * sin(a), .055) + elbow = (spread * .6 * cos(a), spread * .6 * sin(a), .24) + suffix = str(k + 1) + beam("Leg_Root" + suffix, base, elbow, .09, mat, vertices=5) + beam("Leg_RootUpper" + suffix, elbow, (0, .02, top), .12, + mat, vertices=5) + ellipsoid("Leg_RootToe" + suffix, base, (.16, .10, .055), mat) + + +def _mist_robe(mat, upgraded=False): + # Alternating long cloth points touch the floor; the upper body floats. + cone("Body_Robe", (0, .035, .49), .31 if upgraded else .25, + .13, .74, mat["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + _spike("Body_ClothPoint" + str(k), + (.16 * cos(a), .035 + .16 * sin(a), .35), + (.31 * cos(a), .035 + .27 * sin(a), .015), .11, + mat["secondary"] if k % 2 else mat["primary"]) + ellipsoid("Body_Chest", (0, 0, .90), (.23, .16, .23), mat["secondary"]) + + +def _glut_ranged(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_Core", (0, .035, .69), (.30 if up else .21, .22, .27), + m["primary"]) + ellipsoid("Head_Helm", (0, -.015, 1.12), (.19, .16, .20), m["light"]) + _eyes((0, -.17, 1.13), m["secondary"]) + box("Body_Ember", (0, -.197, .71), (.11, .045, .19), m["secondary"]) + if up: + # Broad glass bow arms distinguish the upgrade from the slender lance. + box("Weapon_Rail", (0, -.20, .96), (.10, .98, .09), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .2, 0, .88), (s * .30, -.15, .91), + .075, m["primary"], vertices=6) + _spike("Weapon_GlassBow" + suffix, (s * .06, -.25, .99), + (s * .62, -.04, 1.25), .16, m["secondary"]) + beam("Weapon_String" + suffix, (s * .62, -.04, 1.25), + (0, .22, 1.03), .012, m["light"], vertices=4) + beam("Weapon_Bolt", (0, .20, 1.02), (0, -.64, 1.02), .025, m["light"]) + _spike("Weapon_BoltHead", (0, -.57, 1.02), (0, -.80, 1.02), + .08, m["secondary"]) + else: + beam("ArmL", (-.15, 0, .89), (-.25, -.07, .70), .07, m["primary"]) + beam("ArmR", (.15, 0, .90), (.30, -.19, .91), .075, m["primary"]) + beam("Weapon_Lance", (.29, .34, .81), (.29, -.60, 1.05), .038, + m["accent"]) + _spike("Weapon_GlassTip", (.29, -.53, 1.03), (.29, -.81, 1.11), + .105, m["secondary"]) + + +def _nieten_ranged(up, m): + _mechanical_legs(m) + cone("Body_Cuirass", (0, .02, .78), .21, .27, .43, m["primary"], vertices=6) + box("Body_Plate", (0, -.18, .80), (.27, .09, .22), m["secondary"]) + beam("Head_Neck", (0, 0, 1.0), (0, 0, 1.10), .075, m["accent"]) + box("Head_Housing", (0, -.015, 1.22), (.29, .25, .25), m["light"]) + box("Head_Visor", (0, -.146, 1.23), (.18, .028, .05), m["primary"]) + weapon_x = 0 if up else .29 + beam("ArmL", (-.21, 0, .92), (-.28, -.13, .77), .065, m["accent"]) + beam("ArmR", (.21, 0, .92), (weapon_x + .07, -.24, .91), .065, + m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Weapon_Rail" + suffix, (weapon_x + s * .055, -.30, .97), + (.055, .82 if up else .61, .07), m["accent"]) + tip = (weapon_x + s * (.44 if up else .23), -.27, .97) + beam("Weapon_Bow" + suffix, (weapon_x, -.43, .97), tip, .055, + m["secondary"], vertices=6) + beam("Weapon_String" + suffix, tip, (weapon_x, .02, .97), .011, + m["light"], vertices=4) + _spike("Weapon_Bolt", (weapon_x, -.44, .98), + (weapon_x, -.78 if up else -.66, .98), .052, m["light"]) + if up: + box("Weapon_Sight", (0, -.13, 1.08), (.08, .25, .09), m["primary"]) + _spike("Head_Crest", (0, .03, 1.34), (0, .10, 1.58), .075, + m["secondary"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Arm" + suffix + "_Pauldron", (s * .27, .01, .96), + (.16, .25, .13), m["secondary"]) + + +def _nebel_ranged(up, m): + _mist_robe(m, up) + _mask("Head_Mask", (0, -.105, 1.18), 1.0, m["light"], m["primary"]) + _leaf("Head_Hood", (0, .055, 1.16), .35, .37, m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, 0, .94), (s * .31, -.18, .77), + .055, m["secondary"], vertices=5) + horn_sides = (-1, 1) if up else (1,) + for s in horn_sides: + suffix = "L" if s < 0 else "R" + root = (s * .25, -.12, .79) + elbow = (s * .46, .07, 1.08 if up else .97) + mouth = (s * (.48 if up else .31), -.03, 1.27 if up else 1.02) + beam("Weapon_HornStem" + suffix, root, elbow, .055, m["secondary"]) + beam("Weapon_HornCurve" + suffix, elbow, mouth, .072, m["light"]) + _horn("Weapon_HornBell" + suffix, mouth, .19 if up else .16, + .40 if up else .49, m["light"]) + axis = _unit((0, -1, .18)) + lip = _add(mouth, _mul(axis, .39 if up else .48)) + _lathe("Weapon_MintLip" + suffix, lip, + [(.19 if up else .16, 0), (.19 if up else .16, .025), + (.16 if up else .132, .025), (.16 if up else .132, 0)], + m["accent"], axis) + + +def _wurzel_ranged(up, m): + _root_feet(m["primary"], 3, .34, .56) + ellipsoid("Body_Trunk", (0, .025, .76), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.025, 1.13), (.17, .15, .20), m["secondary"]) + _eyes((0, -.17, 1.13), m["accent"], spread=.057, scale=.03) + _leaf("Body_LeafMantle", (0, -.14, .59), .43, .40, m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + shoulder = (s * .17, 0, .91) + hand = (s * .29, -.21, .85) + beam("Arm" + suffix, shoulder, hand, .07, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .26, -.13, .81), .21, .26, + m["secondary"], lean=s * .1) + beam("Weapon_VineLower", (.28, -.17, .73), (.44, -.08, .93), .046, + m["primary"], vertices=5) + beam("Weapon_VineUpper", (.44, -.08, .93), (.40, -.17, 1.17), .04, + m["primary"], vertices=5) + _cup("Weapon_SeedCapsule", (.24, -.19, .88), .19 if up else .15, + .20, m["accent"], axis=(0, -.7, .7), segments=8) + ellipsoid("Weapon_Seed", (.24, -.30, 1.02), (.075, .075, .10), m["light"]) + if up: + # Overlapping tiers make a pinecone crown, not a mushroom cap. + for layer in range(3): + z = 1.24 + layer * .10 + radius = .23 - layer * .035 + cone("Head_ConeTier" + str(layer), (0, .025, z), radius, + radius * .47, .16, m["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + layer * .3 + _leaf("Head_ConeScale" + str(layer) + "_" + str(k), + (radius * .75 * cos(a), .025 + radius * .75 * sin(a), z - .05), + .11, .16, m["accent"]) + else: + _leaf("Head_LeafCrest", (0, .04, 1.22), .22, .25, m["accent"], .08) + + +def _glut_artillery(up, m): + _basalt_legs(m["primary"], True) + ellipsoid("Body_Foundation", (0, .025, .48), (.39, .31, .22), m["primary"]) + _cup("Weapon_Crater", (0, .02, .52), .55 if up else .43, + .63 if up else .50, m["primary"], segments=12) + _cup("Weapon_EmberLining", (0, .02, .66), .37 if up else .29, + .24 if up else .20, m["secondary"], segments=10) + for s, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Arm" + suffix + "_Slab", (s * .39, .0, .65), + (.13, .19, .25), m["primary"]) + ellipsoid("Head_Eye" + suffix, (s * .13, -.28, .53), + (.055, .025, .035), m["secondary"]) + for k in range(3 if up else 2): + ellipsoid("Weapon_Coal" + str(k), + ((k - (1 if up else .5)) * .12, .015, .80 if up else .77), + (.105, .10, .10), m["accent"]) + if up: + for k in range(5): + a = .2 + pi * k / 4 + _spike("Body_CraterFin" + str(k), + (.40 * cos(a), .03 + .39 * sin(a), .87), + (.46 * cos(a), .03 + .43 * sin(a), 1.37), .095, + m["primary"]) + + +def _nieten_artillery(up, m): + _mechanical_legs(m, True) + box("Body_Chassis", (0, .035, .67), (.56 if up else .45, .37, .34), + m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Piston", (s * .25, .1, .60), + (s * .34, .17, .96), .065, m["accent"]) + cylinder("Arm" + suffix + "_Collar", (s * .31, .15, .84), .095, + .15, m["secondary"], vertices=8) + bell_positions = (-.29, .29) if up else (0,) + for i, x in enumerate(bell_positions): + base = (x, .08, .92) + _horn("Weapon_Resonator" + str(i), base, .27 if up else .34, + .48, m["secondary"], axis=(0, -1, .3)) + # A dark interior cavity and a slim central piston remain visible. + beam("Weapon_Clapper" + str(i), (x, .045, .94), (x, -.26, 1.035), + .038, m["accent"]) + ellipsoid("Weapon_ClapperHead" + str(i), (x, -.27, 1.04), + (.09, .07, .09), m["light"]) + box("Head_Visor", (0, -.164, .68), (.20, .03, .075), m["light"]) + for x, suffix in ((-.24, "L"), (.24, "R")): + cylinder("Body_Exhaust" + suffix, (x, .25, 1.03), .075, + .50 if up else .34, m["accent"], vertices=8) + if up: + box("Body_Brow", (0, -.10, 1.34), (.66, .14, .085), m["primary"]) + cone("Head_Metronome", (0, -.03, 1.47), .10, 0, .20, + m["light"], vertices=4) + + +def _nebel_artillery(up, m): + # Face forward/slightly up: the cavity remains visible to an elevated camera. + _mist_robe(m, up) + bell_base = (0, -.16, 1.05 if up else .85) + radius, depth = (.45, .60) if up else (.38, .50) + _horn("Body_CathedralBell", bell_base, radius, depth, + m["light"], axis=(0, -1, .12)) + beam("Weapon_ClapperStem", (0, -.27, 1.09 if up else .90), + (0, -.70 if up else -.60, 1.0 if up else .80), .045, m["accent"]) + ellipsoid("Weapon_Clapper", (0, -.73 if up else -.63, 1.0 if up else .80), + (.13, .10, .13), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, .02, .96), + (s * .44, -.08, .63), .07, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .44, -.08, .63), + (s * .49, -.19, .94), .10, m["primary"]) + _mask("Head_Mask", (0, .035, 1.49 if up else 1.38), .65, + m["secondary"], m["accent"]) + if up: + for i, x in enumerate((-.27, 0, .27)): + beam("Head_SpireBase" + str(i), (x * .65, .08, 1.16), + (x, .09, 1.42), .075, m["primary"], vertices=5) + _spike("Head_Spire" + str(i), (x, .09, 1.40), + (x * .65, -.01, 1.71 if i == 1 else 1.59), + .075, m["light"]) + + +def _mushroom(name, loc, radius, height, m): + x, y, z = loc + cone(name + "_Stem", (x, y, z + height * .45), .095, .07, height * .9, + m["primary"], vertices=7) + # An angular overhanging cap and light gill ring form a readable roof. + cone(name + "_Gills", (x, y, z + height * .86), radius * .91, + radius * .5, .10, m["accent"], vertices=10) + cone(name + "_Cap", (x, y, z + height), radius, radius * .15, + .22, m["light"], vertices=10) + + +def _wurzel_artillery(up, m): + _root_feet(m["primary"], 5, .50 if up else .43, .56) + ellipsoid("Body_Moss", (0, .02, .48), (.32, .26, .18), m["secondary"]) + _cup("Weapon_SporeChalice", (0, -.10, .50), .40 if up else .43, + .43, m["light"], segments=12) + _cup("Weapon_SporeInterior", (0, -.10, .60), .28, .18, + m["secondary"], segments=10) + for i, x in enumerate((-.105, .105)): + ellipsoid("Weapon_Spore" + str(i), (x, -.08, .81), + (.06, .06, .075), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + _leaf("Arm" + suffix + "_Leaf", (s * .30, -.05, .46), .20, .36, + m["accent"], lean=s * .14) + if up: + _mushroom("Body_RoofL", (-.34, .12, .47), .30, .67, m) + _mushroom("Body_RoofR", (.34, .18, .47), .29, .81, m) + _mushroom("Body_RoofCrown", (0, .33, .54), .39, .98, m) + for x, suffix in ((-.12, "L"), (.12, "R")): + beam("Body_Buttress" + suffix, (x * 3, .33, .12), + (x, .31, 1.21), .075, m["primary"], vertices=5) + + +def _glut_support(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_FurnaceBack", (0, .11, .79), + (.34 if up else .28, .20, .37), m["primary"]) + _cup("Body_OpenHearth", (0, .015, .85), .28 if up else .23, + .33, m["accent"], axis=(0, -1, 0), segments=8) + ellipsoid("Body_Ember", (0, -.10, .85), (.12, .085, .15), m["secondary"]) + ellipsoid("Head_Capstone", (0, .01, 1.17), (.21, .17, .15), m["light"]) + _eyes((0, -.15, 1.16), m["secondary"], spread=.075) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .26, .01, .92), + (s * .33, -.33, .63), .09, m["primary"], vertices=6) + _cup("Weapon_WarmingBowl", (0, -.38, .52), .36 if up else .29, + .22, m["accent"], segments=10) + ellipsoid("Weapon_WarmCoal", (0, -.38, .61), (.15, .12, .07), + m["secondary"]) + if up: + # Upper-half sun rays stay behind the face, safely within the footprint. + for k in range(7): + a = pi * k / 6 + start = (.30 * cos(a), .09, 1.12 + .30 * sin(a)) + end = (.48 * cos(a), .11, 1.12 + .48 * sin(a)) + _spike("Head_SunRay" + str(k), start, end, .065, m["accent"]) + cone("Head_Crown", (0, .0, 1.34), .16, .23, .12, + m["accent"], vertices=8) + + +def _nieten_support(up, m): + _mechanical_legs(m, up) + cone("Body_Coat", (0, .02, .73), .37 if up else .24, + .20, .51, m["primary"], vertices=6) + box("Body_PendulumCase", (0, -.18, .79), (.18, .10, .30), m["secondary"]) + beam("Body_Pendulum", (0, -.24, .89), (.045, -.24, .64), .018, m["accent"]) + ellipsoid("Body_PendulumWeight", (.045, -.24, .65), (.07, .035, .07), + m["light"]) + ellipsoid("Head_Casing", (0, .015, 1.14), (.17, .14, .17), m["accent"]) + ellipsoid("Head_Dial", (0, -.119, 1.14), (.135, .025, .135), m["light"]) + beam("Head_DialHand", (0, -.15, 1.14), (.055, -.15, 1.22), .015, + m["primary"], vertices=4) + for s, suffix in ((-1, "L"), (1, "R")): + elbow = (s * .35, .0, .91) + hand = (s * .45, -.13, 1.10 if s > 0 else .89) + beam("Arm" + suffix + "_Upper", (s * .2, .02, .95), elbow, .06, + m["accent"]) + beam("Arm" + suffix + "_Fore", elbow, hand, .047, m["secondary"]) + ellipsoid("Arm" + suffix + "_Hand", hand, (.065, .065, .065), m["light"]) + beam("Weapon_Baton", (.45, -.13, 1.06), (.61, -.22, 1.45), .019, + m["light"], vertices=5) + if up: + for k, x in enumerate((-.18, 0, .18)): + _spike("Head_CrownTine" + str(k), (x, .015, 1.28), + (x, .015, 1.56 if k == 1 else 1.47), .06, + m["secondary"]) + box("Head_MetronomeBridge", (0, .015, 1.36), (.45, .12, .07), + m["secondary"]) + for s in (-1, 1): + _leaf("Body_CoatTail" + str(s), (s * .20, .20, .33), .24, .59, + m["secondary"], lean=s * .16) + else: + _spike("Head_Spindle", (0, .015, 1.28), (0, .015, 1.45), .055, + m["secondary"]) + + +def _nebel_support(up, m): + _mist_robe(m, up) + _mask("Head_MainMask", (0, -.13, 1.17), 1.0, m["light"], m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Lower", (s * .17, 0, .88), + (s * .37, -.04, .82), .062, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .37, -.04, .82), + (s * .49, -.04, 1.21), .095, m["primary"]) + _leaf("Body_SickleCollar" + suffix, (s * .13, .02, .88), .29, + .43 if up else .29, m["secondary"], lean=s * .29) + if up: + positions = ((-.51, -.035, 1.46), (0, .11, 1.65), (.51, -.035, 1.46)) + for i, p in enumerate(positions): + _mask("Head_CompanionMask" + str(i), p, .67, + m["light"], m["primary"]) + for i, x in enumerate((-.12, 0, .12)): + _spike("Head_Crown" + str(i), (x, -.035, 1.31), + (x * 1.2, -.035, 1.53 if i == 1 else 1.45), .045, + m["accent"]) + else: + _mask("Head_CompanionMask0", (.49, -.035, 1.44), .70, + m["light"], m["primary"]) + ellipsoid("Body_ChoirGem", (0, -.19, .83), (.055, .035, .09), m["accent"]) + + +def _flower(name, loc, scale, m): + for k in range(5): + a = 2 * pi * k / 5 + ellipsoid(name + "_Petal" + str(k), + (loc[0] + cos(a) * .09 * scale, + loc[1] + sin(a) * .09 * scale, loc[2]), + (.085 * scale, .07 * scale, .035 * scale), m["light"]) + ellipsoid(name + "_Heart", (loc[0], loc[1], loc[2] + .025 * scale), + (.052 * scale, .052 * scale, .035 * scale), m["accent"]) + + +def _wurzel_support(up, m): + _root_feet(m["primary"], 5 if up else 3, .45 if up else .31, .55) + # Two counter-leaning stems create an open woven body in the upgrade. + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_WovenRoot" + suffix, (s * .20, .02, .38), + (-s * .17, .015, .83), .105, m["primary"], vertices=5) + beam("Body_WovenRootTop" + suffix, (-s * .17, .015, .83), + (s * .11, .025, 1.16), .085, m["primary"], vertices=5) + else: + ellipsoid("Body_Trunk", (0, .025, .72), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.03, 1.12), (.15, .14, .18), m["secondary"]) + _eyes((0, -.17, 1.12), m["accent"], spread=.05, scale=.026) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .15, 0, .94), + (s * .28, -.27, .69), .065, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .23, -.21, .68), .21, .28, + m["secondary"], lean=s * .12) + _cup("Weapon_LeafBasin", (0, -.31, .62), .30 if up else .23, + .20, m["accent"], segments=8) + # Water uses the optional shared mint accent, with a leaf-colour fallback. + # Opaque faceted geometry avoids sorting issues until the VFX integration. + water = m.get("water", m["accent"]) + cylinder("Weapon_Pool", (0, -.31, .739), .21 if up else .145, + .025, water, vertices=10) + ellipsoid("Weapon_Dew", (0, -.31, .86), (.085, .075, .13), water) + _spike("Weapon_DewTip", (0, -.31, .93), (0, -.31, 1.035), .059, water) + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_CanopyStem" + suffix, (s * .17, .11, .88), + (s * .36, .14, 1.28), .055, m["primary"], vertices=5) + _leaf("Head_Canopy" + suffix, (s * .12, .10, 1.17), .56, .36, + m["secondary"], lean=s * .28) + _flower("Head_Flower" + suffix, (s * .31, .12, 1.43), 1.0, m) + _flower("Head_FlowerCrown", (0, .07, 1.53), .9, m) + else: + _leaf("Head_LeafCap", (0, .02, 1.23), .33, .25, m["accent"], -.06) + + +_RANGED = {"glutpakt": _glut_ranged, "nietenkonvent": _nieten_ranged, + "nebelchor": _nebel_ranged, "wurzelbund": _wurzel_ranged} +_ARTILLERY = {"glutpakt": _glut_artillery, "nietenkonvent": _nieten_artillery, + "nebelchor": _nebel_artillery, "wurzelbund": _wurzel_artillery} +_SUPPORT = {"glutpakt": _glut_support, "nietenkonvent": _nieten_support, + "nebelchor": _nebel_support, "wurzelbund": _wurzel_support} + + +def build_ranged(spec, mat): + """Build IDs *05 (base) and *06 (upgraded).""" + _RANGED[spec["faction"]](spec["upgraded"], mat) + + +def build_artillery(spec, mat): + """Build IDs *07 (base) and *08 (upgraded).""" + _ARTILLERY[spec["faction"]](spec["upgraded"], mat) + + +def build_support(spec, mat): + """Build IDs *09 (base) and *10 (upgraded).""" + _SUPPORT[spec["faction"]](spec["upgraded"], mat) diff --git a/assets-source/phase4/blender/catalog.py b/assets-source/phase4/blender/catalog.py new file mode 100644 index 0000000..e867cf5 --- /dev/null +++ b/assets-source/phase4/blender/catalog.py @@ -0,0 +1,62 @@ +"""Art parameters only; combat statistics remain in Godot's DataCatalog. + +Edit HEIGHTS, FOOTPRINT or individual specs to change proportions. Upgraded +models switch geometry in their builder; they are never only enlarged copies. +""" +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parent +PROJECT = ROOT.parents[2] +SOURCE = ROOT.parent +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' +DEFAULT_BLEND_DIR = SOURCE / 'blend' +FOOTPRINT = 1.85 # Fits inside a 2m construction cell, including weapons. +HEIGHTS = {'melee': 1.35, 'tank': 1.35, 'ranged': 1.45, 'artillery': 1.35, 'support': 1.45} + + +def specs(): + plan = json.loads((PROJECT / 'assets-source/phase3/asset_plan.json').read_text())['assets'] + result = [] + for asset in plan: + if asset['kind'] not in ('unit_icon', 'mercenary_icon'): + continue + number = int(asset['id'][1:]) + if asset['kind'] == 'unit_icon': + roles = ['melee', 'tank', 'ranged', 'artillery', 'support'] + if asset['faction'] in ('nietenkonvent', 'nebelchor'): + roles[0], roles[1] = roles[1], roles[0] + role = roles[(number - 1) // 2] + upgraded = number % 2 == 0 + height = HEIGHTS[role] + (0.15 if upgraded else 0) + else: + role, upgraded, height = 'mercenary', False, 1.4 + (0.15 if number == 5 else 0) + result.append({'id': asset['id'], 'name': asset['display_name'], + 'faction': asset['faction'], 'palette': asset['faction'], + 'role': role, 'upgraded': upgraded, 'height': height, + 'footprint': FOOTPRINT, 'file': 'unit_' + asset['id'] + '.glb'}) + result.extend([ + {'id': 'worker', 'name': 'Funkenleser', 'faction': 'neutral', 'palette': 'worker', + 'role': 'worker', 'upgraded': False, 'height': 1.1, 'footprint': 1.4, 'file': 'worker.glb'}, + {'id': 'map_lane_segment', 'name': 'Lane-Segment', 'faction': 'terrain', 'palette': 'terrain', + 'role': 'lane', 'upgraded': False, 'height': 0, 'file': 'map_lane_segment.glb'}, + *[{'id': 'core_team' + str(team), 'name': 'Saumkern · Team ' + str(team), + 'faction': 'team' + str(team), 'palette': 'team' + str(team), 'role': 'core', + 'team': team, 'upgraded': False, 'height': 2.2, 'footprint': 3.2, + 'file': 'core_team' + str(team) + '.glb'} for team in (0, 1)] + ]) + enemies=[('e01','Splitterling',1.05,1.85),('e02','Schalenläufer',1.42,1.85),('e03','Nebelrest',1.9,1.55),('e04','Fadenschütze',1.8,1.85),('e05','Bruchstampfer',2.0,2.1),('e06','Knotenrufer',2.0,1.9),('e07','Bruchhirsch',2.6,2.5),('e08','Riegelkoloss',2.6,2.7),('e09','Maskenrichter',2.9,2.6),('e10','Schlundkrone',2.9,3.1)] + for id,name,height,footprint in enemies: + result.append({'id':id,'name':name,'faction':'rift','palette':'neutral','role':'enemy','upgraded':False,'height':height,'footprint':footprint,'file':'enemy_'+id+'.glb'}) + for spec in result: + if spec['faction'] in ('glutpakt','wurzelbund','rift','neutral') or spec['role'] in ('lane','core'): + spec['triangle_budget'] = 180000 + spec['detail_level'] = 'high' + return result + + +def get_spec(asset_id): + for spec in specs(): + if spec['id'] == asset_id: + return dict(spec) + raise ValueError('Unknown asset ID: ' + asset_id) diff --git a/assets-source/phase4/blender/common.py b/assets-source/phase4/blender/common.py new file mode 100644 index 0000000..62a3d57 --- /dev/null +++ b/assets-source/phase4/blender/common.py @@ -0,0 +1,148 @@ +"""Shared primitive helpers. Blender coordinates: +Z up, -Y forward. + +Every helper creates one named, flat-shaded part. No joining, textures, scene +deletion or export here. Angles are radians; sizes are metres. +""" +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result diff --git a/assets-source/phase4/blender/environment.py b/assets-source/phase4/blender/environment.py new file mode 100644 index 0000000..fcb41f4 --- /dev/null +++ b/assets-source/phase4/blender/environment.py @@ -0,0 +1,352 @@ +"""Modular terrain, team cores and neutral figures for the Saumwacht asset set. + +Blender coordinates: Z up, forward -Y. This module only constructs meshes; +the caller owns collection cleanup, material creation, export and validation. +""" + +from math import cos, pi, sin + +from common import box, ellipsoid, cylinder, cone, beam, ring, mesh_object, empty + + +def _prism(name, outline, front_y, back_y, material): + """Extrude an X/Z outline along Y, useful for readable masks and wedges.""" + area = sum(outline[i][0] * outline[(i + 1) % len(outline)][1] + - outline[(i + 1) % len(outline)][0] * outline[i][1] + for i in range(len(outline))) + if area < 0: + outline = list(reversed(outline)) + count = len(outline) + vertices = [(x, front_y, z) for x, z in outline] + vertices += [(x, back_y, z) for x, z in outline] + faces = [tuple(range(count)), tuple(range(2 * count - 1, count - 1, -1))] + for i in range(count): + following = (i + 1) % count + faces.append((i, i + count, following + count, following)) + return mesh_object(name, vertices, faces, material) + + +def _figure(spec, nominal_height): + """Scaled primitive wrappers keep species proportions stable at any height.""" + scale = float(spec.get("height", nominal_height)) / nominal_height + + def point(value): + return tuple(component * scale for component in value) + + class Figure: + def box(self, name, loc, size, material, rotation=None): + return box(name, point(loc), point(size), material, rotation=rotation) + + def ellipsoid(self, name, loc, size, material, subdivisions=1): + return ellipsoid(name, point(loc), point(size), material, subdivisions=subdivisions) + + def cylinder(self, name, loc, radius, depth, material, vertices=8, rotation=None): + return cylinder(name, point(loc), radius * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def cone(self, name, loc, radius1, radius2, depth, material, vertices=8, rotation=None): + return cone(name, point(loc), radius1 * scale, radius2 * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def beam(self, name, start, end, radius, material, vertices=6): + return beam(name, point(start), point(end), radius * scale, + material, vertices=vertices) + + def ring(self, name, loc, major_radius, minor_radius, material, + rotation=None, segments=10): + return ring(name, point(loc), major_radius * scale, minor_radius * scale, + material, rotation=rotation, segments=segments) + + def prism(self, name, outline, front_y, back_y, material): + return _prism(name, [(x * scale, z * scale) for x, z in outline], + front_y * scale, back_y * scale, material) + + return Figure() + + +def _boots(f, material, x=0.22, width=0.26, height=0.18, depth=0.42): + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side + "_Boot", (sign * x, -0.075, height / 2), + (width, depth, height), material) + + +def _eyes(f, material, z, y, separation=0.10): + for side, sign in (("L", -1), ("R", 1)): + f.box("Head_Eye" + side, (sign * separation, y, z), + (0.065, 0.025, 0.034), material) + + +def build_lane(spec, mat): + """12 m traversable width, 4 m repeat length, deck at Z=0. + + Side decoration remains strictly outside X=[-6,+6], and nothing extends + past Y=[-2,+2], so consecutive copies meet without a transverse obstacle. + """ + box("Body_LaneFoundation", (0, 0, -0.195), (12, 4, 0.31), mat["primary"]) + for column in range(6): + box("Body_LaneSlab_%02d" % column, (-5 + column * 2, 0, -0.02), + (2, 4, 0.04), mat["primary"]) + for side, sign in (("L", -1), ("R", 1)): + box("Body_" + side + "RetainingLip", (sign * 6.15, 0, -0.10), + (0.30, 4, 0.50), mat["secondary"]) + for index, y in enumerate((-1.42, 0, 1.42)): + ellipsoid("Body_" + side + "Basalt_%02d" % index, + (sign * 6.46, y, -0.05), + (0.26, 0.42, 0.26 if index != 1 else 0.30), mat["secondary"]) + for index, y in enumerate((-1.15, 1.15)): + box("Body_" + side + "BrassMarker_%02d" % index, + (sign * 6.15, y, 0.165), (0.19, 0.20, 0.03), mat["accent"]) + ellipsoid("Body_" + side + "Moss", (sign * 6.39, 0.65, 0.02), + (0.17, 0.34, 0.13), mat["light"]) + empty("Anchor_Deck", (0, 0, 0)) + empty("Anchor_JoinNorth", (0, 2, 0)) + empty("Anchor_JoinSouth", (0, -2, 0)) + + +def build_core(spec, mat): + """A grounded crystal cradle with a physical team circle or triangle.""" + triangular = int(spec.get("team", 0)) == 1 + sides = 3 if triangular else 12 + cylinder("Body_CorePlinth", (0, 0, 0.13), 1.26, 0.26, + mat["primary"], vertices=sides) + cylinder("Body_BrassPlinthRim", (0, 0, 0.285), 1.18, 0.05, + mat["secondary"], vertices=sides) + cylinder("Body_CradleStep", (0, 0, 0.37), 0.85, 0.12, + mat["primary"], vertices=8) + if triangular: + points = [(1.06 * sin(i * 2 * pi / 3), -1.06 * cos(i * 2 * pi / 3), 0.34) + for i in range(3)] + for i in range(3): + beam("Team_Triangle_%d" % i, points[i], points[(i + 1) % 3], + 0.045, mat["accent"], vertices=6) + else: + ring("Team_Circle", (0, 0, 0.345), 1.025, 0.045, mat["accent"], segments=20) + # Multiple low-poly rings create a recognizable mineral, not a sphere. + vertices = [(0, 0, 0.51)] + for radius, z in ((0.37, 0.70), (0.58, 1.16), (0.36, 1.72)): + vertices.extend((radius * cos(i * pi / 3), radius * sin(i * pi / 3), z) + for i in range(6)) + vertices.append((0, 0, 2.20)) + faces = [(0, 1 + (i + 1) % 6, 1 + i) for i in range(6)] + for row in range(2): + start = 1 + 6 * row + for i in range(6): + following = (i + 1) % 6 + faces.append((start + i, start + following, + start + 6 + following, start + 6 + i)) + faces.extend((13 + i, 13 + (i + 1) % 6, 19) for i in range(6)) + mesh_object("Body_CoreCrystal", vertices, faces, mat["accent"]) + for index in range(4): + angle = pi / 4 + index * pi / 2 + x, y = sin(angle), cos(angle) + beam("Arm_Cradle_%d" % index, (x * 0.72, y * 0.72, 0.42), + (x * 0.47, y * 0.47, 0.88), 0.075, mat["secondary"]) + ellipsoid("Arm_CradleClasp_%d" % index, + (x * 0.48, y * 0.48, 0.85), (0.12, 0.12, 0.09), mat["light"]) + empty("Anchor_CoreEffect", (0, 0, 1.25)) + + +def build_worker(spec, mat): + """Small clay Funkenleser with a fork and a framed energy container.""" + f = _figure(spec, 1.1) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.14, depth=0.31) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.16, 0, 0.14), + (sign * 0.15, 0, 0.36), 0.10, mat["primary"]) + f.ellipsoid("Body_Clay", (0, 0, 0.49), (0.30, 0.21, 0.30), mat["primary"]) + f.prism("Body_Apron", [(-0.20, 0.68), (-0.24, 0.30), (0.24, 0.30), (0.20, 0.68)], + -0.23, -0.19, mat["secondary"]) + f.box("Body_Buckle", (0, -0.248, 0.56), (0.10, 0.035, 0.07), mat["accent"]) + f.ellipsoid("Head_Hood", (0, 0.005, 0.88), (0.26, 0.235, 0.22), mat["secondary"]) + f.ellipsoid("Head_ClayFace", (0, -0.175, 0.88), (0.195, 0.10, 0.17), mat["primary"]) + _eyes(f, mat["secondary"], 0.905, -0.274, separation=0.075) + f.beam("ArmL", (-0.23, 0, 0.64), (-0.40, -0.19, 0.52), 0.085, mat["primary"]) + f.beam("ArmR", (0.23, 0, 0.64), (0.39, -0.23, 0.54), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.40, -0.19, 0.52), (0.105, 0.09, 0.09), mat["primary"]) + f.ellipsoid("ArmR_Hand", (0.39, -0.23, 0.54), (0.105, 0.09, 0.09), mat["primary"]) + f.beam("Weapon_SparkForkHandle", (-0.43, -0.20, 0.13), (-0.43, -0.20, 0.78), + 0.032, mat["accent"]) + for sign in (-1, 1): + f.beam("Weapon_SparkForkProng_%d" % sign, (-0.43, -0.20, 0.78), + (-0.43 + sign * 0.10, -0.20, 0.99), 0.026, mat["accent"]) + f.cylinder("Weapon_ContainerBase", (0.44, -0.24, 0.32), 0.11, 0.045, mat["accent"]) + f.cylinder("Weapon_ContainerLid", (0.44, -0.24, 0.61), 0.11, 0.045, mat["accent"]) + # An open brass cage gives glass-like legibility without alpha sorting. + for index in range(4): + angle = index * pi / 2 + f.beam("Weapon_ContainerRib_%d" % index, + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.33), + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.60), + 0.016, mat["accent"], vertices=4) + f.ellipsoid("Weapon_CapturedSpark", (0.44, -0.24, 0.47), + (0.058, 0.058, 0.105), mat["light"]) + + +def _scout(spec, mat): + f = _figure(spec, 1.70) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.18) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.18, 0, 0.17), + (sign * 0.15, 0, 0.78), 0.087, mat["primary"]) + f.box("Leg" + side + "_ShinPlate", (sign * 0.18, -0.095, 0.35), + (0.13, 0.05, 0.24), mat["secondary"]) + f.cone("Body_Armor", (0, 0, 0.97), 0.22, 0.28, 0.49, mat["primary"], vertices=6) + f.box("Body_Belt", (0, 0, 0.77), (0.44, 0.30, 0.10), mat["secondary"]) + f.ellipsoid("Head_Hood", (0, 0.015, 1.42), (0.23, 0.21, 0.25), mat["primary"]) + f.cone("Head_HoodPoint", (0, 0.055, 1.60), 0.145, 0, 0.20, mat["primary"], vertices=5) + f.prism("Head_Mask", [(-0.15, 1.54), (-0.13, 1.32), (0, 1.26), (0.13, 1.32), (0.15, 1.54)], + -0.21, -0.165, mat["light"]) + _eyes(f, mat["primary"], 1.46, -0.225, separation=0.075) + f.beam("ArmL_Upper", (-0.24, 0, 1.12), (-0.34, -0.17, 0.96), 0.078, mat["primary"]) + f.beam("ArmL_Fore", (-0.34, -0.17, 0.96), (-0.06, -0.37, 1.02), 0.071, mat["primary"]) + f.beam("ArmR_Upper", (0.24, 0, 1.12), (0.35, -0.15, 0.97), 0.078, mat["primary"]) + f.beam("ArmR_Fore", (0.35, -0.15, 0.97), (0.25, -0.43, 1.07), 0.071, mat["primary"]) + f.box("Weapon_DartLauncherStock", (0.19, -0.34, 1.07), (0.19, 0.44, 0.15), mat["secondary"]) + f.cylinder("Weapon_DartLauncherBarrel", (0.19, -0.66, 1.09), + 0.065, 0.34, mat["light"], rotation=(pi / 2, 0, 0)) + f.cylinder("Weapon_DartLauncherBore", (0.19, -0.836, 1.09), + 0.04, 0.008, mat["primary"], rotation=(pi / 2, 0, 0)) + f.box("Body_DartQuiver", (-0.14, 0.23, 1.02), (0.23, 0.17, 0.45), mat["secondary"], + rotation=(0, -0.16, 0)) + for index in range(3): + x = -0.23 + index * 0.085 + f.beam("Weapon_SpareDart_%d" % index, (x, 0.24, 1.10), (x - 0.06, 0.24, 1.47), + 0.024, mat["light"], vertices=4) + + +def _ram(spec, mat): + f = _figure(spec, 1.48) + _boots(f, mat["primary"], x=0.27, width=0.35, height=0.20, depth=0.45) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.27, 0, 0.35), (0.25, 0.30, 0.35), mat["primary"]) + f.ellipsoid("Arm" + side + "_Pauldron", (sign * 0.43, 0, 1.05), + (0.27, 0.25, 0.25), mat["secondary"]) + f.box("Body_RustArmor", (0, 0, 0.83), (0.74, 0.48, 0.67), mat["secondary"]) + f.box("Body_UpperLamella", (0, -0.256, 1.01), (0.71, 0.06, 0.18), mat["primary"]) + f.box("Body_LowerLamella", (0, -0.261, 0.80), (0.71, 0.06, 0.16), mat["primary"]) + f.ellipsoid("Head_Helmet", (0, 0, 1.29), (0.27, 0.23, 0.19), mat["primary"]) + f.box("Head_BrowGuard", (0, -0.23, 1.35), (0.45, 0.085, 0.10), mat["light"]) + _eyes(f, mat["accent"], 1.275, -0.235) + f.beam("ArmL", (-0.43, 0, 1.03), (-0.43, -0.40, 0.81), 0.14, mat["primary"]) + f.beam("ArmR", (0.43, 0, 1.03), (0.61, -0.18, 0.72), 0.14, mat["primary"]) + f.box("ArmR_HammerFist", (0.61, -0.19, 0.66), (0.30, 0.28, 0.29), mat["secondary"]) + outline = [(-0.63, 1.09), (-0.68, 0.34), (-0.48, 0.21), (0.45, 0.21), + (0.65, 0.34), (0.60, 1.09)] + f.prism("Weapon_RamShield", outline, -0.54, -0.39, mat["secondary"]) + f.box("Weapon_ShieldTopRim", (-0.015, -0.575, 1.05), (1.18, 0.07, 0.095), mat["light"]) + f.prism("Weapon_CentralWedge", [(-0.13, 0.94), (-0.18, 0.37), (0, 0.28), (0.18, 0.37), (0.13, 0.94)], + -0.74, -0.53, mat["primary"]) + + +def _singer(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.12, depth=0.32) + f.cone("Body_BellRobe", (0, 0, 0.63), 0.43, 0.20, 1.10, mat["primary"], vertices=8) + for index, x in enumerate((-0.22, 0, 0.22)): + f.prism("Body_RobeFold_%d" % index, + [(x - 0.055, 0.15), (x + 0.055, 0.15), (x * 0.45, 1.09)], + -0.32, -0.24, mat["accent"]) + f.ellipsoid("Body_Mantle", (0, 0, 1.24), (0.37, 0.27, 0.21), mat["accent"]) + f.ellipsoid("Head_DeepHood", (0, 0, 1.57), (0.26, 0.25, 0.25), mat["primary"]) + f.prism("Head_SingerMask", [(-0.13, 1.68), (-0.12, 1.47), (0, 1.41), (0.12, 1.47), (0.13, 1.68)], + -0.246, -0.21, mat["light"]) + _eyes(f, mat["primary"], 1.60, -0.257, separation=0.065) + f.beam("ArmL", (-0.29, 0, 1.27), (-0.34, -0.37, 1.05), 0.085, mat["primary"]) + f.beam("ArmR", (0.29, 0, 1.27), (0.36, -0.43, 1.10), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.34, -0.37, 1.05), (0.095, 0.075, 0.075), mat["light"]) + f.ellipsoid("ArmR_Hand", (0.36, -0.43, 1.10), (0.095, 0.075, 0.075), mat["light"]) + f.beam("Weapon_HornPipe", (-0.30, -0.37, 1.08), (0.36, -0.43, 1.13), 0.075, mat["secondary"]) + # A true open bell: two rings connected by a tapered shell, no filled mouth. + vertices = [] + for y, radius in ((-0.43, 0.075), (-0.84, 0.28), (-0.81, 0.235), (-0.47, 0.042)): + for index in range(10): + angle = index * pi / 5 + vertices.append((0.36 + cos(angle) * radius, y, 1.13 + sin(angle) * radius)) + faces = [] + for row in range(3): + for i in range(10): + j = (i + 1) % 10 + faces.append((row * 10 + i, row * 10 + j, (row + 1) * 10 + j, (row + 1) * 10 + i)) + scale = float(spec.get("height", 1.82)) / 1.82 + mesh_object("Weapon_ResonanceHorn", [tuple(v * scale for v in point) for point in vertices], + faces, mat["secondary"]) + f.ring("Weapon_HornRim", (0.36, -0.84, 1.13), 0.258, 0.023, mat["light"], + rotation=(pi / 2, 0, 0)) + + +def _breaker(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.28, width=0.36, height=0.22, depth=0.49) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.26, 0, 0.47), (0.28, 0.31, 0.54), mat["primary"]) + f.box("Leg" + side + "_Knee", (sign * 0.27, -0.19, 0.51), + (0.27, 0.13, 0.24), mat["secondary"]) + f.box("Arm" + side + "_Pauldron", (sign * 0.48, 0, 1.29), + (0.42, 0.52, 0.34), mat["primary"], rotation=(0, sign * 0.14, 0)) + f.cone("Body_SteelTorso", (0, 0, 1.01), 0.35, 0.47, 0.70, mat["primary"], vertices=6) + f.prism("Body_RustChestInset", [(-0.28, 1.29), (0, 0.95), (0.28, 1.29)], + -0.397, -0.35, mat["secondary"]) + f.box("Head_Helmet", (0, 0, 1.61), (0.43, 0.40, 0.42), mat["primary"]) + f.prism("Head_Faceplate", [(-0.17, 1.76), (-0.17, 1.50), (0, 1.44), (0.17, 1.50), (0.17, 1.76)], + -0.23, -0.19, mat["light"]) + f.box("Head_Visor", (0, -0.246, 1.66), (0.25, 0.026, 0.045), mat["primary"]) + f.beam("ArmL", (-0.47, 0, 1.25), (-0.31, -0.50, 0.92), 0.12, mat["primary"]) + f.beam("ArmR", (0.47, 0, 1.25), (0.30, -0.50, 1.20), 0.12, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.31, -0.50, 0.92), (0.145, 0.12, 0.12), mat["secondary"]) + f.ellipsoid("ArmR_Hand", (0.30, -0.50, 1.20), (0.145, 0.12, 0.12), mat["secondary"]) + f.beam("Weapon_HammerShaft", (-0.65, -0.51, 0.77), (0.66, -0.51, 1.36), + 0.055, mat["secondary"]) + f.prism("Weapon_KeilhammerHead", [(0.40, 1.26), (0.43, 1.58), (0.82, 1.80), + (1.02, 1.61), (0.90, 1.18)], + -0.79, -0.24, mat["primary"]) + # Offset along the sloped edge normal; coplanar cap faces would flicker. + f.prism("Weapon_ChiselEdge", [(0.832, 1.814), (1.032, 1.624), (0.992, 1.354), (0.932, 1.644)], + -0.80, -0.23, mat["light"]) + + +def _rift(spec, mat): + f = _figure(spec, 2.08) + _boots(f, mat["primary"], x=0.22, width=0.21, height=0.12, depth=0.35) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side + "_Shin", (sign * 0.22, 0, 0.12), + (sign * 0.30, 0.12, 0.45), 0.069, mat["primary"]) + f.beam("Leg" + side + "_Thigh", (sign * 0.30, 0.12, 0.45), + (sign * 0.17, 0, 0.81), 0.083, mat["primary"]) + f.ellipsoid("Body_Pelvis", (0, 0, 0.83), (0.25, 0.16, 0.16), mat["primary"]) + # Separate ribs bound real negative space; there is deliberately no chest fill. + for side, sign in (("L", -1), ("R", 1)): + f.beam("Body_" + side + "LowerRib", (sign * 0.15, 0, 0.89), + (sign * 0.31, 0, 1.18), 0.095, mat["primary"]) + f.beam("Body_" + side + "UpperRib", (sign * 0.31, 0, 1.18), + (sign * 0.21, 0, 1.52), 0.10, mat["primary"]) + f.beam("Body_" + side + "RiftSeam", (sign * 0.17, -0.080, 0.95), + (sign * 0.245, -0.080, 1.18), 0.019, mat["accent"], vertices=4) + f.beam("Body_" + side + "RiftUpperSeam", (sign * 0.245, -0.080, 1.18), + (sign * 0.16, -0.080, 1.46), 0.019, mat["accent"], vertices=4) + f.beam("Body_Collar", (-0.21, 0, 1.52), (0.21, 0, 1.52), 0.095, mat["primary"]) + f.ellipsoid("Head_HollowShell", (0, 0, 1.73), (0.20, 0.155, 0.23), mat["primary"]) + f.box("Head_RiftMouth", (0, -0.153, 1.69), (0.17, 0.025, 0.043), mat["accent"]) + for index, (x, z) in enumerate(((-0.19, 1.90), (-0.10, 2.02), (0.10, 2.02), (0.19, 1.90))): + f.beam("Head_BrokenCrown_%d" % index, (x, 0, z - 0.13), (x * 1.18, 0, z + 0.06), + 0.038, mat["light"], vertices=5) + f.beam("ArmL_Upper", (-0.30, 0, 1.47), (-0.48, 0.02, 1.13), 0.068, mat["primary"]) + f.beam("ArmL_Fore", (-0.48, 0.02, 1.13), (-0.46, -0.18, 0.77), 0.056, mat["primary"]) + for index in range(3): + f.beam("ArmL_Claw_%d" % index, (-0.50 + index * 0.043, -0.18, 0.79), + (-0.51 + index * 0.049, -0.25, 0.64), 0.020, mat["light"], vertices=4) + f.beam("ArmR_Upper", (0.30, 0, 1.47), (0.49, 0, 1.10), 0.068, mat["primary"]) + f.beam("ArmR_Fore", (0.49, 0, 1.10), (0.37, -0.33, 1.23), 0.056, mat["primary"]) + f.ellipsoid("ArmR_CradlingHand", (0.37, -0.33, 1.23), (0.12, 0.09, 0.052), mat["primary"]) + f.ellipsoid("Weapon_DrainOrb", (0.37, -0.34, 1.40), (0.13, 0.13, 0.13), mat["accent"]) + f.ring("Weapon_DrainOrbit", (0.37, -0.34, 1.40), 0.175, 0.015, + mat["light"], rotation=(0.35, 0.20, 0), segments=10) + + +def build_mercenary(spec, mat): + """Dispatch five neutral mercenaries, retaining recognizable role silhouettes.""" + builders = {"s01": _scout, "s02": _ram, "s03": _singer, + "s04": _breaker, "s05": _rift} + identifier = str(spec["id"]) + if identifier not in builders: + raise ValueError("Unknown Saumwacht mercenary: " + identifier) + builders[identifier](spec, mat) diff --git a/assets-source/phase4/blender/frontline.py b/assets-source/phase4/blender/frontline.py new file mode 100644 index 0000000..66427e5 --- /dev/null +++ b/assets-source/phase4/blender/frontline.py @@ -0,0 +1,557 @@ +"""Original Saumwacht melee and tank silhouettes, built from named low-poly parts. + +Coordinates are metres, Z up, facing -Y. The shared exporter owns materials, +normalisation, parenting, animation, scene lifetime and export. Every builder is +deterministic and deliberately preserves separate limb / weapon meshes. +""" + +from math import cos, sin, pi + +from common import box, ellipsoid, cylinder, cone, beam, ring, mesh_object, empty + + +def _profile(name, points, y, depth, mat): + """Extrude a silhouette with outward normals and a centred editable origin.""" + signed_area = sum(points[i][0] * points[(i+1) % len(points)][1] + - points[(i+1) % len(points)][0] * points[i][1] + for i in range(len(points))) + if signed_area < 0: + points = list(reversed(points)) + center_x = (min(p[0] for p in points) + max(p[0] for p in points)) / 2 + center_z = (min(p[1] for p in points) + max(p[1] for p in points)) / 2 + n = len(points) + vertices = [(x-center_x, -depth/2, z-center_z) for x, z in points] + vertices += [(x-center_x, depth/2, z-center_z) for x, z in points] + faces = [tuple(range(n)), tuple(range(2 * n - 1, n - 1, -1))] + faces += [(i, i + n, (i + 1) % n + n, (i + 1) % n) for i in range(n)] + obj = mesh_object(name, vertices, faces, mat) + obj.location = (center_x, y, center_z) + return obj + + +def _slab(name, loc, size, mat, bevel=0.08): + """Eight-sided shield / armour plate with real clipped corners.""" + x, y, z = loc + w, d, h = size + a, b = w / 2, h / 2 + c = min(bevel, a * 0.42, b * 0.42) + points = [(x-a+c, z-b), (x+a-c, z-b), (x+a, z-b+c), + (x+a, z+b-c), (x+a-c, z+b), (x-a+c, z+b), + (x-a, z+b-c), (x-a, z-b+c)] + return _profile(name, points, y, d, mat) + + +def _blade(name, origin, length, width, angle, mat, depth=0.055, hook=0.12): + """A broad bent blade, with an unmistakable edge rather than a thin rod.""" + x, y, z = origin + local = [(-width*.38, 0), (width*.48, 0), + (width*.54, length*.52), (hook, length), + (-width*.30, length*.65)] + points = [(x + u*cos(angle) + v*sin(angle), + z - u*sin(angle) + v*cos(angle)) for u, v in local] + return _profile(name, points, y, depth, mat) + + +def _crescent(name, origin, radius, thickness, start, end, mat, + depth=0.09, segments=10): + """An open polygonal crescent plate in the front plane, angles in radians.""" + x, y, z = origin + angles = [start + (end-start)*i/segments for i in range(segments+1)] + points = [(x + radius*cos(a), z + radius*sin(a)) for a in angles] + points += [(x + (radius-thickness)*cos(a), + z + (radius-thickness)*sin(a)) for a in reversed(angles)] + return _profile(name, points, y, depth, mat) + + +def _eyes(prefix, x, y, z, spacing, mat, width=0.085): + for side, s in (("L", -1), ("R", 1)): + box(prefix + "Eye" + side, (x+s*spacing, y, z), + (width, 0.023, 0.028), mat) + + +def _stone_legs(mat, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (0.27 if upgraded else 0.24) + _slab("Leg" + side + "Shin", (x, 0.02, 0.26), + (0.30, 0.31, 0.36), mat["primary"]) + _slab("Leg" + side + "Foot", (x, -0.10, 0.095), + (0.37, 0.46, 0.19), mat["primary"], 0.07) + if upgraded: + box("Leg" + side + "Cuff", (x, -0.167, 0.27), + (0.23, 0.035, 0.07), mat["accent"]) + + +def _coal_body(mat, upgraded): + ellipsoid("BodyCoal", (0, 0.01, 0.77), (0.44, 0.35, 0.48), + mat["primary"], subdivisions=2) + _slab("BodyForehead", (0, -0.16, 1.115), (0.62, 0.36, 0.25), + mat["primary"]) + mouth = [(-.31,.83), (-.23,.77), (-.12,.80), (0,.735), + (.13,.785), (.24,.76), (.31,.83), (.25,.94), + (.1,.92), (0,.97), (-.14,.93), (-.27,.955)] + _profile("HeadEmberMouth", mouth, -.352, .045, mat["secondary"]) + _eyes("Head", 0, -.350, 1.05, .155, mat["secondary"], .065) + for i, x in enumerate((-.20, 0, .20)): + _profile("HeadTooth%02d" % i, + [(x-.035,.94), (x,.865), (x+.035,.94)], + -.384, .025, mat["light"]) + for side, s in (("L", -1), ("R", 1)): + if upgraded: + _slab("BodyShoulder" + side, (s*.49, .0, 1.08), + (.39, .47, .32), mat["primary"]) + _blade("BodyShoulderCrest" + side, (s*.42, .035, 1.15), + .29, .16, s*.50, mat["primary"], .17, s*.04) + box("BodyShoulderSeam" + side, (s*.50, -.243, 1.05), + (.22, .02, .055), mat["secondary"]) + else: + ellipsoid("BodyShoulder" + side, (s*.41, .02, .87), + (.19, .25, .25), mat["primary"]) + + +def _coal_claws(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Upper", (s*.37, .0, .86), + (s*.55, -.075, .65), .13, mat["primary"]) + ellipsoid("Arm" + side + "Fist", (s*.57, -.16, .56), + (.19, .24, .19), mat["primary"]) + for i, dx in enumerate((-.105, .105)): + x = s*.57 + dx + # Curved front claws are separate wedges; upgrade adds long tips. + points = [(x-.045,.60), (x+.045,.60), (x+.065,.42), + (x+.015,.30 if upgraded else .37), + (x-.035,.43)] + _profile("Weapon" + side + "Claw%02d" % i, points, + -.39 if upgraded else -.34, .115, + mat["accent"] if upgraded else mat["light"]) + if upgraded: + _slab("Arm" + side + "WristGuard", (s*.57, -.18, .70), + (.33, .40, .13), mat["accent"], .045) + + +def _basalt_body(mat, upgraded): + _slab("BodyBastion", (0, .035, .83), + (1.02 if upgraded else .87, .57, .95), mat["primary"]) + _slab("BodyFrontShield", (0, -.30, .80), (.74, .18, .71), + mat["primary"], .14) + _slab("HeadFurnaceSlot", (0, -.401, 1.07), (.48, .035, .085), + mat["secondary"], .025) + for s in (-1, 1): + beam("BodyBrace" + ("L" if s < 0 else "R"), + (s*.29, -.398, .50), (s*.29, -.398, .95), + .033, mat["accent"], vertices=4) + if upgraded: + for i, (x, z, width) in enumerate(((-.48, 1.20, .31), + (0, 1.30, .43), + (.48, 1.20, .31))): + _slab("BodyBattlement%02d" % i, (x, .035, z), + (width, .54, .35), mat["primary"], .05) + box("BodyBattlementCap%02d" % i, (x, .035, z+.145), + (width+.025, .565, .055), mat["accent"]) + _slab("BodyShieldBoss", (0, -.41, .73), (.38, .075, .35), + mat["accent"], .095) + _slab("BodyShieldCore", (0, -.456, .73), (.23, .025, .22), + mat["secondary"], .065) + + +def _basalt_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + x = s * (.635 if upgraded else .54) + _slab("Arm" + side + "Pillar", (x, .01, .72), + (.28, .37, .60), mat["primary"]) + _slab("Arm" + side + "Fist", (x, -.075, .48), + (.32, .42, .27), mat["primary"]) + box("Arm" + side + "Band", (x, -.287, .52), + (.23, .028, .07), mat["accent"]) + + +def _machine_legs(mat, upgraded=False, tall=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (.25 if tall else .24) + top = .72 if tall else .46 + knee = (x*1.15, .03, .38 if tall else .25) + ankle = (x, -.065, .13) + beam("Leg" + side + "PistonUpper", (x*.8, .035, top), knee, + .07 if tall else .13, mat["accent"]) + beam("Leg" + side + "PistonLower", knee, ankle, + .055 if tall else .09, mat["accent"]) + cylinder("Leg" + side + "Knee", knee, .085 if tall else .13, + .16, mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + _slab("Leg" + side + "Shoe", (x, -.105, .065), + (.23 if tall else .33, .36, .13), mat["primary"], .04) + if upgraded: + _slab("Leg" + side + "Greave", (x, -.115, .25), + (.17 if tall else .27, .12, .23), mat["primary"], .04) + + +def _machine_mask(mat, z=1.22): + _profile("HeadCeramicMask", [(-.14,z-.11), (.14,z-.11), + (.17,z+.06), (0,z+.18), (-.17,z+.06)], + -.205, .12, mat["light"]) + _eyes("Head", 0, -.272, z+.025, .067, mat["primary"], .060) + + +def _shear_body(mat, upgraded): + ellipsoid("BodySpindle", (0, .02, .91), + (.285 if upgraded else .21, .235, .32), mat["primary"]) + cylinder("BodyOcherHub", (0, -.224, .87), .14, .07, + mat["secondary"], vertices=10, rotation=(pi/2, 0, 0)) + cylinder("BodyHubPin", (0, -.267, .87), .057, .025, + mat["accent"], vertices=8, rotation=(pi/2, 0, 0)) + _machine_mask(mat, 1.235) + if upgraded: + _slab("BodyHubArmor", (0, .15, .98), (.57, .21, .37), + mat["primary"]) + cone("HeadFin", (0, .055, 1.385), .065, 0, .21, + mat["secondary"], vertices=4) + + +def _shear_weapons(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + if upgraded: + for i, (z, angle) in enumerate(((1.10, .62), (.89, 1.32), + (.66, 2.07))): + pivot = (s*.47, -.105, z) + beam("Arm" + side + "Link%02d" % i, + (s*.21, .02, .93), pivot, .049, mat["secondary"]) + cylinder("Arm" + side + "Hub%02d" % i, pivot, .076, + .10, mat["secondary"], vertices=8, + rotation=(pi/2, 0, 0)) + _blade("Weapon" + side + "Blade%02d" % i, + (pivot[0], -.17, z), .39, .105, s*angle, + mat["accent"], .055, s*.07) + else: + pivot = (s*.43, -.12, .95) + beam("Arm" + side + "Upper", (s*.16, .025, 1.0), + (s*.34, .04, .82), .065, mat["secondary"]) + beam("Arm" + side + "Forearm", (s*.34, .04, .82), + pivot, .060, mat["primary"]) + for i, angle in enumerate((.39, 1.07)): + _blade("Weapon" + side + "Shear%02d" % i, + (pivot[0], -.19-i*.045, pivot[2]), .42, .10, + s*angle, mat["accent"], .055, s*.035) + cylinder("Weapon" + side + "ShearPivot", (s*.43, -.264, .95), + .092, .055, mat["secondary"], vertices=10, + rotation=(pi/2, 0, 0)) + + +def _boiler_body(mat, upgraded): + cylinder("BodyBoiler", (0, .01, .77), .385, .66, + mat["primary"], vertices=12) + cone("BodyBoilerLid", (0, .01, 1.115), .39, .27, .14, + mat["primary"], vertices=12) + ring("BodyLowerRim", (0, .01, .475), .38, .035, + mat["secondary"], segments=12) + _slab("HeadCeramicFace", (0, -.355, .98), (.32, .105, .19), + mat["light"], .04) + _eyes("Head", 0, -.414, 1.005, .074, mat["primary"], .060) + cylinder("BodyGaugeRim", (0, -.402, .695), .117, .07, + mat["secondary"], vertices=12, rotation=(pi/2, 0, 0)) + cylinder("BodyGaugeFace", (0, -.444, .695), .085, .016, + mat["light"], vertices=12, rotation=(pi/2, 0, 0)) + beam("BodyGaugeNeedle", (0, -.458, .695), (.047, -.458, .747), + .012, mat["primary"], vertices=4) + if upgraded: + _slab("BodyChestArmor", (0, -.10, .82), (.81, .55, .61), + mat["primary"], .12) + # Face and gauge sit ahead of the armour, never buried inside it. + for side, s in (("L", -1), ("R", 1)): + cylinder("BodyPressureCylinder" + side, (s*.48, .06, 1.075), + .145, .54, mat["primary"], vertices=10) + cylinder("BodyPressureCap" + side, (s*.48, .06, 1.36), + .16, .07, mat["secondary"], vertices=10) + beam("BodyPressurePipe" + side, (s*.48, .13, .84), + (s*.30, .25, .66), .048, mat["accent"]) + box("HeadBrow", (0, -.37, 1.12), (.46, .17, .09), mat["light"]) + else: + cylinder("BodyChimney", (.235, .10, 1.245), .08, .23, + mat["accent"], vertices=8) + cylinder("BodyChimneyLip", (.235, .10, 1.365), .10, .045, + mat["secondary"], vertices=8) + + +def _boiler_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Piston", (s*.33, .0, .88), + (s*.52, -.02, .63), .09, mat["accent"]) + _slab("Arm" + side + "Fist", (s*.53, -.11, .53), + (.29, .34, .28), mat["accent"], .045) + if upgraded and side == "L": + _slab("WeaponLPressureShield", (-.57, -.245, .75), + (.37, .20, .69), mat["primary"], .08) + _slab("WeaponLShieldStripe", (-.57, -.356, .75), + (.085, .025, .50), mat["secondary"], .025) + elif upgraded: + cylinder("WeaponRPistonCap", (.55, -.302, .59), .165, .08, + mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + + +def _mist_legs(mat, tall=False, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + hip = (s*.12, .045, .71 if tall else .48) + knee = (s*.25, .06 if side == "L" else -.04, .32) + ankle = (s*.20, -.12 if side == "L" else .02, .095) + beam("Leg" + side + "FoldUpper", hip, knee, + .10 if tall else .13, mat["primary"], vertices=5) + beam("Leg" + side + "FoldLower", knee, ankle, .075, + mat["secondary"], vertices=5) + _profile("Leg" + side + "TendrilFoot", + [(s*.20-.09,.035), (s*.20+.11,.035), + (s*.20+.07,.14), (s*.20-.045,.20)], + ankle[1]-.045, .20, mat["primary"]) + + +def _mist_mask(mat, z, large=False): + sx, sz = (.235, .29) if large else (.158, .218) + ellipsoid("HeadMistMask", (0, -.17, z), (sx, .105, sz), + mat["light"], subdivisions=2) + _eyes("Head", 0, -.273, z+.035, sx*.43, mat["accent"], sx*.42) + _profile("HeadMaskChin", [(-sx*.50,z-.10), (0,z-sz*.92), + (sx*.50,z-.10)], -.252, .022, mat["light"]) + + +def _dancer_body(mat, upgraded): + _profile("BodyFoldedRibbon", [(-.16,.56), (.10,.60), (.205,.97), + (.105,1.16), (-.06,1.13), (-.195,.86)], + .025, .27, mat["primary"]) + _profile("BodyVioletFold", [(-.145,.64), (-.04,.67), (.15,1.075), + (.05,1.12)], -.13, .038, mat["secondary"]) + _mist_mask(mat, 1.23) + if upgraded: + _crescent("HeadCrescentCrest", (0, .005, 1.37), .20, .065, + .08*pi, .92*pi, mat["secondary"], .075, 8) + _blade("BodyBackRibbonL", (-.12,.15,.94), .40, .13, -.9, + mat["secondary"], .06, -.05) + _blade("BodyBackRibbonR", (.12,.15,.94), .40, .13, .9, + mat["secondary"], .06, .05) + + +def _dancer_weapons(mat, upgraded): + if upgraded: + # One large open scissor: two distinct sweeping blades at one mint hub. + pivot = (.19, -.32, .79) + beam("ArmLUpper", (-.14,.015,1.05), (-.33,-.11,.85), + .065, mat["secondary"], vertices=5) + beam("ArmLForearm", (-.33,-.11,.85), pivot, + .061, mat["primary"], vertices=5) + beam("ArmRUpper", (.14,.015,1.05), (.36,-.12,.96), + .065, mat["primary"], vertices=5) + beam("ArmRForearm", (.36,-.12,.96), pivot, + .061, mat["secondary"], vertices=5) + _blade("WeaponScissorUpper", pivot, .69, .18, .57, + mat["light"], .075, .09) + _blade("WeaponScissorLower", (.19,-.405,.79), .66, .18, 1.42, + mat["light"], .075, .04) + ring("WeaponScissorHandleL", (.04,-.37,.655), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + ring("WeaponScissorHandleR", (-.005,-.37,.79), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + cylinder("WeaponScissorMintPivot", (.19,-.463,.79), .087, .028, + mat["accent"], vertices=12, rotation=(pi/2,0,0)) + else: + for side, s, high in (("L", -1, False), ("R", 1, True)): + elbow = (s*.31, -.04, .91 if high else .80) + wrist = (s*.43, -.12, 1.07 if high else .66) + beam("Arm" + side + "Upper", (s*.14,.01,1.02), elbow, + .065, mat["primary"], vertices=5) + beam("Arm" + side + "Forearm", elbow, wrist, + .052, mat["secondary"], vertices=5) + _blade("Weapon" + side + "ThreadBlade", wrist, + .40, .065, s*(.50 if high else 2.12), + mat["light"], .045, s*.045) + cylinder("Weapon" + side + "MintGrip", wrist, .060, .09, + mat["accent"], vertices=8, rotation=(pi/2,0,0)) + + +def _mist_tank_body(mat, upgraded): + ellipsoid("BodyFoldedMist", (0,.035,.73), (.37,.25,.44), + mat["primary"], subdivisions=2) + _profile("BodyVioletCenterFold", [(-.22,.43), (.035,.39), + (.25,.90), (.04,1.09)], + -.205, .060, mat["secondary"]) + _mist_mask(mat, 1.145, large=True) + _crescent("BodyFrontCrescent", (0,-.32,.89), .44, .145, + .98*pi, 2.02*pi, mat["secondary"], .15, 12) + if upgraded: + _crescent("BodyOuterShield", (0,-.245,.99), .655, .17, + .89*pi, 2.11*pi, mat["light"], .15, 12) + _crescent("BodyRearShield", (0,.11,1.025), .60, .16, + .05*pi, .95*pi, mat["secondary"], .17, 12) + for side, s in (("L",-1),("R",1)): + _blade("BodyShieldWing" + side, (s*.44,.005,.72), + .49,.23,s*.39,mat["secondary"],.16,s*.10) + _blade("BodyShieldMintEdge" + side, (s*.49,-.09,.79), + .31,.047,s*.39,mat["accent"],.025,s*.065) + + +def _mist_tank_arms(mat, upgraded): + for side, s in (("L",-1),("R",1)): + beam("Arm" + side + "Fold", (s*.31,.005,.92), + (s*.43,-.045,.67), .080, mat["primary"], vertices=5) + _crescent("Arm" + side + "Crescent", (s*.42,-.14,.72), + .24,.075, -.4*pi if s < 0 else .6*pi, + .6*pi if s < 0 else 1.6*pi, + mat["secondary"],.095,8) + + +def _root_legs(mat, upgraded=False, four=False, spread=.32): + positions = [("L", -1, -.035), ("R", 1, -.035)] + if four: + positions = [("LFront",-1,-.27),("RFront",1,-.27), + ("LRear",-1,.28),("RRear",1,.28)] + for label, s, y in positions: + beam("Leg" + label + "Root", (s*spread*.65,y,.48), + (s*spread,y-.035,.13), .11 if four else .13, + mat["primary"], vertices=6) + _slab("Leg" + label + "Foot", (s*spread,y-.10,.075), + (.28,.36,.15), mat["primary"], .065) + # One broad toe root is stronger at gameplay scale than many twigs. + beam("Leg" + label + "Toe", (s*spread,y-.12,.095), + (s*spread+s*.06,y-.31,.055), .045, + mat["accent"], vertices=5) + + +def _leaf(name, origin, length, width, angle, mat, depth=.055): + x,y,z = origin + local = [(0,0),(width*.55,length*.44),(0,length), + (-width*.55,length*.44)] + points = [(x+u*cos(angle)+v*sin(angle), + z-u*sin(angle)+v*cos(angle)) for u,v in local] + return _profile(name,points,y,depth,mat) + + +def _thorn_body(mat, upgraded): + if upgraded: + ellipsoid("BodyCoiledRoot", (0,.08,.63), (.48,.34,.39), + mat["primary"],subdivisions=2) + ring("BodyRootCoil", (0,.065,.61), .365,.085, + mat["primary"],segments=10) + ellipsoid("HeadUpperJaw", (0,-.16,1.07), (.55,.34,.26), + mat["primary"],subdivisions=2) + _slab("HeadLowerJaw", (0,-.265,.66), (.87,.44,.22), + mat["primary"],.085) + _slab("HeadMouthDepth", (0,-.26,.84), (.78,.20,.28), + mat["secondary"],.08) + for i,x in enumerate((-.30,-.10,.10,.30)): + _profile("WeaponUpperFang%02d" % i, + [(x-.065,1.04),(x,.835),(x+.065,1.04)], + -.485,.055,mat["accent"]) + for i,x in enumerate((-.23,0,.23)): + _profile("WeaponLowerFang%02d" % i, + [(x-.07,.74),(x+.07,.74),(x,.91)], + -.497,.055,mat["accent"]) + for side,s in (("L",-1),("R",1)): + _leaf("HeadCheekLeaf" + side,(s*.40,-.29,.82),.39,.29, + s*.59,mat["secondary"],.11) + _leaf("HeadCrownLeaf" + side,(s*.15,.01,1.21),.23,.15, + s*.67,mat["accent"]) + _eyes("Head",0,-.425,1.155,.24,mat["accent"],.09) + else: + ellipsoid("BodyThornPod", (0,.03,.76), (.43,.34,.43), + mat["primary"],subdivisions=2) + _slab("HeadSlit",(0,-.308,.87),(.29,.045,.075),mat["secondary"],.025) + _eyes("Head",0,-.337,.96,.105,mat["accent"],.055) + for side,s in (("L",-1),("R",1)): + _leaf("HeadSprout" + side,(s*.10,.025,1.09),.31,.19, + s*.55,mat["secondary"],.07) + _blade("WeaponSideThorn" + side,(s*.34,.02,.76), + .24,.13,s*1.36,mat["secondary"],.13,s*.015) + for i,(x,y,z) in enumerate(((-.22,-.08,1.07),(.22,-.08,1.07), + (0,.285,.90))): + cone("BodyThorn%02d" % i,(x,y,z),.09,0,.25, + mat["accent"],vertices=5) + + +def _bark_head(mat, upgraded): + ellipsoid("HeadLowRoot", (0,-.36,.50), (.24,.23,.18), + mat["primary"]) + _eyes("Head",0,-.559,.54,.097,mat["accent"],.077) + if upgraded: + _slab("HeadBrowBark",(0,-.43,.68),(.55,.23,.14), + mat["primary"],.045) + + +def _bark_shell(mat, upgraded): + ellipsoid("BodyCorkShell", (0,.07,.80), (.57,.49,.49), + mat["primary"],subdivisions=2) + if upgraded: + # Three actual layered trunk cross sections, readable from above/front. + for index,(x,y,z,r) in enumerate(((0,-.345,.91,.42), + (-.42,.06,.99,.32), + (.42,.06,.99,.32))): + cylinder("BodyGrowthShield%02d" % index,(x,y,z),r,.17, + mat["primary"],vertices=12,rotation=(pi/2,0,0)) + for band,ratio in enumerate((.80,.50)): + ring("BodyGrowthRing%02d_%02d" % (index,band), + (x,y-.097,z),r*ratio,.022, + mat["accent"],rotation=(pi/2,0,0),segments=12) + cylinder("BodyGrowthHeart%02d" % index,(x,y-.099,z),r*.18,.02, + mat["secondary"],vertices=8,rotation=(pi/2,0,0)) + _leaf("BodyCrownLeafL",(-.09,.16,1.19),.25,.19,-.67, + mat["secondary"],.055) + _leaf("BodyCrownLeafR",(.09,.16,1.19),.25,.19,.67, + mat["accent"],.055) + else: + # Asymmetric overlapping cork plates make a turtle-like living shield. + for i,(x,y,z,w,h) in enumerate(((-.26,-.015,1.04,.39,.36), + (.18,-.07,1.11,.42,.31), + (0,.245,.93,.53,.39))): + _slab("BodyCorkPlate%02d" % i,(x,y,z),(w,.29,h), + mat["primary"],.08) + _leaf("BodyMossPlateL",(-.39,-.065,.87),.24,.20,-.49, + mat["secondary"],.08) + _leaf("BodyMossPlateR",(.31,.04,1.06),.20,.19,.57, + mat["secondary"],.06) + + +def _faction(spec): + faction = str(spec["faction"]).lower() + aliases = {"g":"glutpakt", "m":"nietenkonvent", "n":"nebelchor", + "w":"wurzelbund"} + return aliases.get(faction, faction) + + +def build_melee(spec, mat): + """Build a faction-specific melee unit or its visibly evolved upgrade.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _coal_body(mat, upgraded) + _coal_claws(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded, tall=True) + _shear_body(mat, upgraded) + _shear_weapons(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, tall=True, upgraded=upgraded) + _dancer_body(mat, upgraded) + _dancer_weapons(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=upgraded, spread=.34 if upgraded else .27) + _thorn_body(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht melee faction: " + faction) + + +def build_tank(spec, mat): + """Build a tank; upgrades add fortress tiers, pressure shields or growth rings.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _basalt_body(mat, upgraded) + _basalt_arms(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded) + _boiler_body(mat, upgraded) + _boiler_arms(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, upgraded=upgraded) + _mist_tank_body(mat, upgraded) + _mist_tank_arms(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=True, spread=.38 if upgraded else .33) + _bark_shell(mat, upgraded) + _bark_head(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht tank faction: " + faction) diff --git a/assets-source/phase4/blender/generate_all.py b/assets-source/phase4/blender/generate_all.py new file mode 100644 index 0000000..27898b2 --- /dev/null +++ b/assets-source/phase4/blender/generate_all.py @@ -0,0 +1,40 @@ +"""Blender batch entry: generate all 59 assets, or select an ID/role. + +blender --background --factory-startup --python generate_all.py -- --id g01 +blender --background --factory-startup --python generate_all.py -- --all +""" +import argparse +from pathlib import Path +import sys + +DIRECTORY = Path(__file__).resolve().parent +sys.path.insert(0, str(DIRECTORY)) +from catalog import specs +from pipeline import build_one, write_manifest + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--all', action='store_true') + parser.add_argument('--id', action='append', default=[]) + parser.add_argument('--role') + parser.add_argument('--faction') + parser.add_argument('--export-dir') + parser.add_argument('--blend-dir') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + selected = [s for s in specs() if (not args.id or s['id'] in args.id) + and (not args.role or s['role'] == args.role) + and (not args.faction or s['faction'] == args.faction)] + known = {s['id'] for s in specs()} + if set(args.id) - known or not selected: + raise ValueError('Unknown ID/role selection') + records = [] + for spec in selected: + records.append(build_one(spec['id'], export_dir=args.export_dir, blend_dir=args.blend_dir, keep_scene=False)) + if len(selected) == len(specs()): + write_manifest(records) + print(f'PHASE4_EXPORT_PASS: {len(selected)} models') + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/blender/pipeline.py b/assets-source/phase4/blender/pipeline.py new file mode 100644 index 0000000..9552cd4 --- /dev/null +++ b/assets-source/phase4/blender/pipeline.py @@ -0,0 +1,248 @@ +"""Build in an isolated scene, preserve editable parts, export selected GLB. + +An existing user scene is never cleared. Single entry points leave the generated +scene open; batch generation removes only its own temporary objects afterwards. +""" +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + +from common import empty, make_materials +from catalog import DEFAULT_BLEND_DIR, DEFAULT_EXPORT_DIR, PROJECT, SOURCE, get_spec, specs +from reference_glutpakt import build_glutpakt +from reference_high_detail import build_high_glutpakt, build_high_enemy, enhance_existing, finalize_high_geometry +from reference_nebelchor import build_nebelchor +from reference_nietenkonvent import build_nietenkonvent +from reference_wurzelbund import build_wurzelbund +from reference_living_detail import build_high_wurzelbund, build_high_worker, build_high_core +from reference_neutral import build_neutral +from reference_sculpt_detail import sculpt_game_surfaces, add_offline_sculpt_modifiers, add_offline_materials + + +def _builder(role): + if role in ('melee', 'tank'): + import frontline + return getattr(frontline, 'build_' + role) + if role in ('ranged', 'artillery', 'support'): + import backline + return getattr(backline, 'build_' + role) + import environment + return getattr(environment, 'build_' + role) + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + + +def write_manifest(records=None): + """Use authoritative catalog order; reject incomplete or stale exports.""" + if records is None: + records = [json.loads((SOURCE / 'records' / (spec['id'] + '.json')).read_text()) for spec in specs()] + for record in records: + path = Path(record['export_path']) + if hashlib.sha256(path.read_bytes()).hexdigest() != record['sha256']: + raise ValueError('Export changed since record: ' + record['id']) + value = {'phase': 4, 'asset_count': len(records), 'blender_version': bpy.app.version_string, + 'coordinate_system': 'Metres; glTF/Godot +Y up, +Z forward; ground origin. Lane top at Y=0.', + 'assets': records} + output = PROJECT / 'assets' / 'phase4_manifest.json' + if Path(records[0]['export_path']).parent != DEFAULT_EXPORT_DIR.resolve(): + output = Path(records[0]['export_path']).parent / 'phase4_manifest.json' + output.write_text(json.dumps(value, ensure_ascii=False, indent=2) + '\n') + return records diff --git a/assets-source/phase4/blender/reference_geometry.py b/assets-source/phase4/blender/reference_geometry.py new file mode 100644 index 0000000..ec2fd00 --- /dev/null +++ b/assets-source/phase4/blender/reference_geometry.py @@ -0,0 +1,168 @@ +"""Editable low-poly shapes used for direct Phase-3 icon matching. + +All dimensions are metres, Blender Z-up and -Y forward. Geometry stays solid, +faceted and separated by meaningful part names; there are no image billboards. +""" +from math import sin, cos, pi +from mathutils import Vector +from common import mesh_object, ellipsoid, cylinder, beam, ring + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) diff --git a/assets-source/phase4/blender/reference_glutpakt.py b/assets-source/phase4/blender/reference_glutpakt.py new file mode 100644 index 0000000..2670747 --- /dev/null +++ b/assets-source/phase4/blender/reference_glutpakt.py @@ -0,0 +1,274 @@ +"""Glutpakt rebuilt from the ten actual Phase-3 icons, not role archetypes. + +Shape controls live in the small part functions. G06 is a walking ballista; +G07/08 have massive mortar bodies; G09/10 are headless living hearths. +""" +from math import pi, sin, cos +import bpy +import hashlib +from common import box, ellipsoid, cone, cylinder, beam, ring +from reference_geometry import r_plate, r_block, r_rock, r_sweep, r_lathe, r_band, r_disc, r_inset, r_sun + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) diff --git a/assets-source/phase4/blender/reference_high_detail.py b/assets-source/phase4/blender/reference_high_detail.py new file mode 100644 index 0000000..9bdde87 --- /dev/null +++ b/assets-source/phase4/blender/reference_high_detail.py @@ -0,0 +1,652 @@ +"""Phase 7: authored high-detail basalt/metal figures with real layered geometry. + +Blender Z up, -Y forward. All pieces retain stable semantic names for Godot's +rigid-joint animation. Bevels, armor overlaps, joints, fingers and ornaments +are modeled geometry; no subdivision-only inflation of the former silhouettes. +""" +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector +from common import box, ellipsoid, cylinder, beam, ring, mesh_object, srgb_to_linear +from reference_geometry import r_plate, r_block, r_rock, r_sweep, r_lathe, r_arch_shell + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) diff --git a/assets-source/phase4/blender/reference_living_detail.py b/assets-source/phase4/blender/reference_living_detail.py new file mode 100644 index 0000000..bd21e3d --- /dev/null +++ b/assets-source/phase4/blender/reference_living_detail.py @@ -0,0 +1,422 @@ +"""Authored Phase 9 living wood: braided roots, bark lamellae, leaf veins, +closed petal shells and fungal gills. No subdivision of the old models. +Each rigid root has its own semantic animation joint; all geometry is editable. +""" +from math import sin, cos, pi +import bpy +from mathutils import Vector +from common import ellipsoid, cylinder, mesh_object, srgb_to_linear +from reference_geometry import r_lathe +from reference_high_detail import hd_curve, hd_disc, hd_ring, hd_plate, hd_finish, hd_box, hd_rod, hd_materials + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) diff --git a/assets-source/phase4/blender/reference_nebelchor.py b/assets-source/phase4/blender/reference_nebelchor.py new file mode 100644 index 0000000..0060ff4 --- /dev/null +++ b/assets-source/phase4/blender/reference_nebelchor.py @@ -0,0 +1,206 @@ +"""Nebelchor: flowing ghost ribbons and mask/bell silhouettes from Phase 3.""" +from math import sin, cos, pi +from common import ellipsoid, ring, beam +from reference_geometry import r_plate, r_rock, r_sweep, r_lathe, r_arch_shell + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) diff --git a/assets-source/phase4/blender/reference_neutral.py b/assets-source/phase4/blender/reference_neutral.py new file mode 100644 index 0000000..3ce9257 --- /dev/null +++ b/assets-source/phase4/blender/reference_neutral.py @@ -0,0 +1,180 @@ +"""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) diff --git a/assets-source/phase4/blender/reference_nietenkonvent.py b/assets-source/phase4/blender/reference_nietenkonvent.py new file mode 100644 index 0000000..c6569cb --- /dev/null +++ b/assets-source/phase4/blender/reference_nietenkonvent.py @@ -0,0 +1,197 @@ +"""Mechanical silhouettes matched to the Phase-3 unit icons.""" +from math import sin, cos, pi +from common import box, ellipsoid, cylinder, beam, cone, ring +from reference_geometry import r_plate, r_block, r_sweep, r_lathe, r_band, r_disc, r_inset, r_rock + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) diff --git a/assets-source/phase4/blender/reference_sculpt_detail.py b/assets-source/phase4/blender/reference_sculpt_detail.py new file mode 100644 index 0000000..5cdb21d --- /dev/null +++ b/assets-source/phase4/blender/reference_sculpt_detail.py @@ -0,0 +1,99 @@ +"""Phase 10 sculpt pass: physical eroded stone and furrowed bark. + +Adds mid-frequency relief to selected large surfaces. Flat ornaments, crystal +facets, leaf ribs and joint names are preserved. The editable .blend also keeps +an optional high-resolution sculpt modifier stack; the GLB uses the budgeted +game mesh, so twenty copies of a hero do not load its offline sculpt resolution. +""" +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True diff --git a/assets-source/phase4/blender/reference_wurzelbund.py b/assets-source/phase4/blender/reference_wurzelbund.py new file mode 100644 index 0000000..f92ff6e --- /dev/null +++ b/assets-source/phase4/blender/reference_wurzelbund.py @@ -0,0 +1,215 @@ +"""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) diff --git a/assets-source/phase4/catalog.md b/assets-source/phase4/catalog.md new file mode 100644 index 0000000..4238223 --- /dev/null +++ b/assets-source/phase4/catalog.md @@ -0,0 +1,67 @@ +# Saumwacht · Modellkatalog + +Stand: 17. September 2026. Zwanzig Glutpakt- und Wurzelbund-Figuren, zehn Wellengegner, Arbeiter und Kristalle wurden neu aufgebaut; Söldner und Lane erhielten zusätzliche Details. Die 59 Einträge stammen aus `assets/phase4_manifest.json`. + +Maße in Metern: **B = X, H = Y, T = Z** in Godot, auf zwei Nachkommastellen gerundet. GLBs sind über die IDs verlinkt; native Quellen liegen in `blend/.blend`. [Anleitung](README.md) · [Bildvergleiche](../../docs/screenshots/phase4/reference-gallery.html) + +| ID / GLB | Modell | Fraktion | Rolle | Upgrade | Dreiecke | B (m) | H (m) | T (m) | +| --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: | +| [g01](../../assets/models/unit_g01.glb) | Kohlenbeißer | Glutpakt | Nahkampf | Nein | 79780 | 1.58 | 1.35 | 0.89 | +| [g02](../../assets/models/unit_g02.glb) | Schlackenklaue | Glutpakt | Nahkampf | Ja | 75624 | 1.79 | 1.50 | 0.98 | +| [g03](../../assets/models/unit_g03.glb) | Schlackenwacht | Glutpakt | Tank | Nein | 67232 | 1.78 | 1.35 | 0.87 | +| [g04](../../assets/models/unit_g04.glb) | Basaltbastion | Glutpakt | Tank | Ja | 80764 | 1.51 | 1.50 | 0.74 | +| [g05](../../assets/models/unit_g05.glb) | Funkenlanze | Glutpakt | Fernkampf | Nein | 54710 | 1.57 | 1.45 | 0.45 | +| [g06](../../assets/models/unit_g06.glb) | Glasballiste | Glutpakt | Fernkampf | Ja | 38036 | 1.85 | 1.34 | 1.73 | +| [g07](../../assets/models/unit_g07.glb) | Aschenwerfer | Glutpakt | Artillerie | Nein | 81492 | 1.64 | 1.35 | 1.25 | +| [g08](../../assets/models/unit_g08.glb) | Kraterrufer | Glutpakt | Artillerie | Ja | 77130 | 1.83 | 1.50 | 1.49 | +| [g09](../../assets/models/unit_g09.glb) | Herdhüter | Glutpakt | Unterstützung | Nein | 84568 | 1.25 | 1.45 | 1.08 | +| [g10](../../assets/models/unit_g10.glb) | Sonnenesse | Glutpakt | Unterstützung | Ja | 96706 | 1.33 | 1.60 | 1.17 | +| [m01](../../assets/models/unit_m01.glb) | Kesselwicht | Nietenkonvent | Tank | Nein | 1284 | 1.14 | 1.35 | 0.73 | +| [m02](../../assets/models/unit_m02.glb) | Druckhüter | Nietenkonvent | Tank | Ja | 1360 | 1.21 | 1.50 | 0.60 | +| [m03](../../assets/models/unit_m03.glb) | Scherschreiter | Nietenkonvent | Nahkampf | Nein | 932 | 1.55 | 1.35 | 0.28 | +| [m04](../../assets/models/unit_m04.glb) | Sechsklingler | Nietenkonvent | Nahkampf | Ja | 1398 | 1.64 | 1.50 | 0.30 | +| [m05](../../assets/models/unit_m05.glb) | Bolzenknecht | Nietenkonvent | Fernkampf | Nein | 1148 | 0.77 | 1.45 | 0.81 | +| [m06](../../assets/models/unit_m06.glb) | Linienmeister | Nietenkonvent | Fernkampf | Ja | 1432 | 1.21 | 1.60 | 1.32 | +| [m07](../../assets/models/unit_m07.glb) | Klangkolben | Nietenkonvent | Artillerie | Nein | 740 | 0.84 | 1.35 | 1.00 | +| [m08](../../assets/models/unit_m08.glb) | Resonanzramme | Nietenkonvent | Artillerie | Ja | 1316 | 1.47 | 1.50 | 1.03 | +| [m09](../../assets/models/unit_m09.glb) | Taktspindel | Nietenkonvent | Unterstützung | Nein | 1160 | 1.00 | 1.45 | 0.28 | +| [m10](../../assets/models/unit_m10.glb) | Taktprälat | Nietenkonvent | Unterstützung | Ja | 946 | 1.09 | 1.60 | 0.86 | +| [n01](../../assets/models/unit_n01.glb) | Saummaske | Nebelchor | Tank | Nein | 1132 | 0.89 | 1.35 | 0.39 | +| [n02](../../assets/models/unit_n02.glb) | Grenzmaske | Nebelchor | Tank | Ja | 1156 | 1.28 | 1.50 | 0.42 | +| [n03](../../assets/models/unit_n03.glb) | Fadentänzer | Nebelchor | Nahkampf | Nein | 934 | 0.96 | 1.35 | 0.32 | +| [n04](../../assets/models/unit_n04.glb) | Saumzertrenner | Nebelchor | Nahkampf | Ja | 1360 | 1.11 | 1.50 | 0.39 | +| [n05](../../assets/models/unit_n05.glb) | Fernflüsterer | Nebelchor | Fernkampf | Nein | 1118 | 0.87 | 1.45 | 0.57 | +| [n06](../../assets/models/unit_n06.glb) | Fernrufer | Nebelchor | Fernkampf | Ja | 1498 | 1.66 | 1.60 | 0.64 | +| [n07](../../assets/models/unit_n07.glb) | Glockenschlepper | Nebelchor | Artillerie | Nein | 1274 | 0.71 | 1.35 | 0.75 | +| [n08](../../assets/models/unit_n08.glb) | Hohlgeläut | Nebelchor | Artillerie | Ja | 1482 | 1.09 | 1.50 | 0.83 | +| [n09](../../assets/models/unit_n09.glb) | Maskenkantor | Nebelchor | Unterstützung | Nein | 1314 | 1.09 | 1.45 | 0.36 | +| [n10](../../assets/models/unit_n10.glb) | Vielstimmenkantor | Nebelchor | Unterstützung | Ja | 1734 | 1.01 | 1.60 | 0.35 | +| [w01](../../assets/models/unit_w01.glb) | Dornhopser | Wurzelbund | Nahkampf | Nein | 61376 | 1.00 | 1.35 | 0.87 | +| [w02](../../assets/models/unit_w02.glb) | Rankenschnapper | Wurzelbund | Nahkampf | Ja | 78020 | 1.14 | 1.50 | 1.25 | +| [w03](../../assets/models/unit_w03.glb) | Korkrücken | Wurzelbund | Tank | Nein | 84786 | 0.98 | 1.35 | 0.98 | +| [w04](../../assets/models/unit_w04.glb) | Ringborke | Wurzelbund | Tank | Ja | 134530 | 1.15 | 1.50 | 1.05 | +| [w05](../../assets/models/unit_w05.glb) | Samenschleuder | Wurzelbund | Fernkampf | Nein | 50536 | 0.89 | 1.45 | 0.89 | +| [w06](../../assets/models/unit_w06.glb) | Zapfenkrone | Wurzelbund | Fernkampf | Ja | 62588 | 0.93 | 1.60 | 0.93 | +| [w07](../../assets/models/unit_w07.glb) | Sporenkelch | Wurzelbund | Artillerie | Nein | 69164 | 1.12 | 1.35 | 1.10 | +| [w08](../../assets/models/unit_w08.glb) | Pilzkathedrale | Wurzelbund | Artillerie | Ja | 103748 | 1.19 | 1.50 | 1.00 | +| [w09](../../assets/models/unit_w09.glb) | Tauhüter | Wurzelbund | Unterstützung | Nein | 52040 | 0.92 | 1.45 | 0.92 | +| [w10](../../assets/models/unit_w10.glb) | Quellgeflecht | Wurzelbund | Unterstützung | Ja | 61052 | 1.08 | 1.60 | 1.15 | +| [s01](../../assets/models/unit_s01.glb) | Nadelspäher | Söldner & Arbeiter | Söldner | Nein | 10340 | 0.90 | 1.40 | 0.82 | +| [s02](../../assets/models/unit_s02.glb) | Rostschieber | Söldner & Arbeiter | Söldner | Nein | 12040 | 0.97 | 1.40 | 0.74 | +| [s03](../../assets/models/unit_s03.glb) | Dunstsänger | Söldner & Arbeiter | Söldner | Nein | 7832 | 1.19 | 1.40 | 0.84 | +| [s04](../../assets/models/unit_s04.glb) | Keilbrecher | Söldner & Arbeiter | Söldner | Nein | 10458 | 1.28 | 1.40 | 0.74 | +| [s05](../../assets/models/unit_s05.glb) | Risszehrer | Söldner & Arbeiter | Söldner | Nein | 10440 | 0.85 | 1.55 | 0.36 | +| [worker](../../assets/models/worker.glb) | Funkenleser | Söldner & Arbeiter | Arbeiter | Nein | 24026 | 0.93 | 1.10 | 0.83 | +| [map_lane_segment](../../assets/models/map_lane_segment.glb) | Lane-Segment | Umgebung | Lane-Segment | Nein | 10700 | 13.38 | 0.74 | 4.00 | +| [core_team0](../../assets/models/core_team0.glb) | Saumkern · Team 0 | Umgebung | Saumkern | Nein | 36652 | 2.24 | 2.20 | 2.24 | +| [core_team1](../../assets/models/core_team1.glb) | Saumkern · Team 1 | Umgebung | Saumkern | Nein | 36848 | 2.24 | 2.20 | 2.24 | +| [e01](../../assets/models/enemy_e01.glb) | Splitterling | Risskreaturen | Wellengegner | Nein | 19228 | 1.84 | 1.05 | 1.78 | +| [e02](../../assets/models/enemy_e02.glb) | Schalenläufer | Risskreaturen | Wellengegner | Nein | 20180 | 1.85 | 1.42 | 1.79 | +| [e03](../../assets/models/enemy_e03.glb) | Nebelrest | Risskreaturen | Wellengegner | Nein | 35898 | 1.03 | 1.90 | 0.70 | +| [e04](../../assets/models/enemy_e04.glb) | Fadenschütze | Risskreaturen | Wellengegner | Nein | 51050 | 1.28 | 1.80 | 1.09 | +| [e05](../../assets/models/enemy_e05.glb) | Bruchstampfer | Risskreaturen | Wellengegner | Nein | 62798 | 2.08 | 2.00 | 1.16 | +| [e06](../../assets/models/enemy_e06.glb) | Knotenrufer | Risskreaturen | Wellengegner | Nein | 48336 | 1.30 | 2.00 | 0.76 | +| [e07](../../assets/models/enemy_e07.glb) | Bruchhirsch | Risskreaturen | Wellengegner | Nein | 33800 | 1.52 | 2.60 | 1.99 | +| [e08](../../assets/models/enemy_e08.glb) | Riegelkoloss | Risskreaturen | Wellengegner | Nein | 81240 | 2.39 | 2.60 | 1.17 | +| [e09](../../assets/models/enemy_e09.glb) | Maskenrichter | Risskreaturen | Wellengegner | Nein | 57310 | 1.75 | 2.90 | 0.89 | +| [e10](../../assets/models/enemy_e10.glb) | Schlundkrone | Risskreaturen | Wellengegner | Nein | 64694 | 2.31 | 2.90 | 2.56 | diff --git a/assets-source/phase4/records/core_team0.json b/assets-source/phase4/records/core_team0.json new file mode 100644 index 0000000..5760fd5 --- /dev/null +++ b/assets-source/phase4/records/core_team0.json @@ -0,0 +1,116 @@ +{ + "id": "core_team0", + "name": "Saumkern · Team 0", + "faction": "team0", + "palette": "team0", + "role": "core", + "team": 0, + "upgraded": false, + "height": 2.2, + "footprint": 3.2, + "file": "core_team0.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/core_team0.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team0.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/core_team0.blend", + "triangles": 36652, + "mesh_parts": 64, + "parts": [ + "Body_CoreStep0", + "Body_CoreStepRim0", + "Body_CoreStep1", + "Body_CoreStepRim1", + "Body_CoreStep2", + "Body_CoreStepRim2", + "Body_CoreStep3", + "Body_CoreStepRim3", + "Team_Circle", + "Body_PlinthBlock0", + "Body_Seal0", + "Body_RadialInlay0", + "Body_PlinthBlock1", + "Body_Seal1", + "Body_RadialInlay1", + "Body_PlinthBlock2", + "Body_Seal2", + "Body_RadialInlay2", + "Body_PlinthBlock3", + "Body_Seal3", + "Body_RadialInlay3", + "Body_PlinthBlock4", + "Body_Seal4", + "Body_RadialInlay4", + "Body_PlinthBlock5", + "Body_Seal5", + "Body_RadialInlay5", + "Body_PlinthBlock6", + "Body_Seal6", + "Body_RadialInlay6", + "Body_PlinthBlock7", + "Body_Seal7", + "Body_RadialInlay7", + "Body_PlinthBlock8", + "Body_Seal8", + "Body_RadialInlay8", + "Body_PlinthBlock9", + "Body_Seal9", + "Body_RadialInlay9", + "Body_PlinthBlock10", + "Body_Seal10", + "Body_RadialInlay10", + "Body_PlinthBlock11", + "Body_Seal11", + "Body_RadialInlay11", + "Body_Cradle0", + "Body_CradleCollar0", + "Body_Cradle1", + "Body_CradleCollar1", + "Body_Cradle2", + "Body_CradleCollar2", + "Body_Cradle3", + "Body_CradleCollar3", + "Body_Cradle4", + "Body_CradleCollar4", + "Body_Cradle5", + "Body_CradleCollar5", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Body_CrystalHalo" + ], + "bounds_blender": { + "min": [ + -1.1197097301483154, + -1.1202889680862427, + 0.0 + ], + "max": [ + 1.1197096109390259, + 1.1202890872955322, + 2.200000047683716 + ] + }, + "bounds_godot": { + "min": [ + -1.1197097301483154, + 0.0, + -1.1202890872955322 + ], + "max": [ + 1.1197096109390259, + 2.200000047683716, + 1.1202889680862427 + ] + }, + "scale_applied": 0.9319289899522011, + "blender_version": "5.2.1 LTS", + "sha256": "81a5305fc55482e6ca19524b72787d585211643d8842840efb4bdaf844660181", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 16, + "offline_render_triangles": 344572 +} diff --git a/assets-source/phase4/records/core_team1.json b/assets-source/phase4/records/core_team1.json new file mode 100644 index 0000000..7535b5d --- /dev/null +++ b/assets-source/phase4/records/core_team1.json @@ -0,0 +1,118 @@ +{ + "id": "core_team1", + "name": "Saumkern · Team 1", + "faction": "team1", + "palette": "team1", + "role": "core", + "team": 1, + "upgraded": false, + "height": 2.2, + "footprint": 3.2, + "file": "core_team1.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/core_team1.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team1.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/core_team1.blend", + "triangles": 36848, + "mesh_parts": 66, + "parts": [ + "Body_CoreStep0", + "Body_CoreStepRim0", + "Body_CoreStep1", + "Body_CoreStepRim1", + "Body_CoreStep2", + "Body_CoreStepRim2", + "Body_CoreStep3", + "Body_CoreStepRim3", + "Team_Triangle0", + "Team_Triangle1", + "Team_Triangle2", + "Body_PlinthBlock0", + "Body_Seal0", + "Body_RadialInlay0", + "Body_PlinthBlock1", + "Body_Seal1", + "Body_RadialInlay1", + "Body_PlinthBlock2", + "Body_Seal2", + "Body_RadialInlay2", + "Body_PlinthBlock3", + "Body_Seal3", + "Body_RadialInlay3", + "Body_PlinthBlock4", + "Body_Seal4", + "Body_RadialInlay4", + "Body_PlinthBlock5", + "Body_Seal5", + "Body_RadialInlay5", + "Body_PlinthBlock6", + "Body_Seal6", + "Body_RadialInlay6", + "Body_PlinthBlock7", + "Body_Seal7", + "Body_RadialInlay7", + "Body_PlinthBlock8", + "Body_Seal8", + "Body_RadialInlay8", + "Body_PlinthBlock9", + "Body_Seal9", + "Body_RadialInlay9", + "Body_PlinthBlock10", + "Body_Seal10", + "Body_RadialInlay10", + "Body_PlinthBlock11", + "Body_Seal11", + "Body_RadialInlay11", + "Body_Cradle0", + "Body_CradleCollar0", + "Body_Cradle1", + "Body_CradleCollar1", + "Body_Cradle2", + "Body_CradleCollar2", + "Body_Cradle3", + "Body_CradleCollar3", + "Body_Cradle4", + "Body_CradleCollar4", + "Body_Cradle5", + "Body_CradleCollar5", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Body_CrystalHalo" + ], + "bounds_blender": { + "min": [ + -1.1197097301483154, + -1.1202889680862427, + 0.0 + ], + "max": [ + 1.1197096109390259, + 1.1202890872955322, + 2.200000047683716 + ] + }, + "bounds_godot": { + "min": [ + -1.1197097301483154, + 0.0, + -1.1202890872955322 + ], + "max": [ + 1.1197096109390259, + 2.200000047683716, + 1.1202889680862427 + ] + }, + "scale_applied": 0.9319289899522011, + "blender_version": "5.2.1 LTS", + "sha256": "391bd1a1452d56b75c0cfb1e519381fa37c4efa0d9f1a6f99e1e434b9a8747bb", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 16, + "offline_render_triangles": 344768 +} diff --git a/assets-source/phase4/records/e01.json b/assets-source/phase4/records/e01.json new file mode 100644 index 0000000..cb2860d --- /dev/null +++ b/assets-source/phase4/records/e01.json @@ -0,0 +1,89 @@ +{ + "id": "e01", + "name": "Splitterling", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.05, + "footprint": 1.85, + "file": "enemy_e01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e01.blend", + "triangles": 19228, + "mesh_parts": 38, + "parts": [ + "Body_Core", + "Body_Carapace0", + "Body_SeamGlow0", + "Body_Carapace1", + "Body_SeamGlow1", + "Body_Carapace2", + "Body_SeamGlow2", + "Body_Carapace3", + "Body_SeamGlow3", + "Head_Skull", + "LegL0_Upper", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Inset", + "LegL1_Upper", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Inset", + "LegL2_Upper", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Inset", + "Head_EyeL", + "Head_MandibleL", + "LegR0_Upper", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Inset", + "LegR1_Upper", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Inset", + "LegR2_Upper", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Inset", + "Head_EyeR", + "Head_MandibleR" + ], + "bounds_blender": { + "min": [ + -0.9224945306777954, + -0.8919363021850586, + 0.0 + ], + "max": [ + 0.9224945306777954, + 0.8919363617897034, + 1.0499999523162842 + ] + }, + "bounds_godot": { + "min": [ + -0.9224945306777954, + 0.0, + -0.8919363617897034 + ], + "max": [ + 0.9224945306777954, + 1.0499999523162842, + 0.8919363021850586 + ] + }, + "scale_applied": 1.1583589145245845, + "blender_version": "5.2.1 LTS", + "sha256": "536a33a8595db0283ea08648a4e5f70b7062850308f08179348afc3abe16134a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 166318 +} diff --git a/assets-source/phase4/records/e02.json b/assets-source/phase4/records/e02.json new file mode 100644 index 0000000..d964a85 --- /dev/null +++ b/assets-source/phase4/records/e02.json @@ -0,0 +1,93 @@ +{ + "id": "e02", + "name": "Schalenläufer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.42, + "footprint": 1.85, + "file": "enemy_e02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e02.blend", + "triangles": 20180, + "mesh_parts": 42, + "parts": [ + "Body_Core", + "Body_Carapace0", + "Body_SeamGlow0", + "Body_Spine0", + "Body_Carapace1", + "Body_SeamGlow1", + "Body_Spine1", + "Body_Carapace2", + "Body_SeamGlow2", + "Body_Spine2", + "Body_Carapace3", + "Body_SeamGlow3", + "Body_Spine3", + "Head_Skull", + "LegL0_Upper", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Inset", + "LegL1_Upper", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Inset", + "LegL2_Upper", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Inset", + "Head_EyeL", + "Head_MandibleL", + "LegR0_Upper", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Inset", + "LegR1_Upper", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Inset", + "LegR2_Upper", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Inset", + "Head_EyeR", + "Head_MandibleR" + ], + "bounds_blender": { + "min": [ + -0.9249999523162842, + -0.8943588137626648, + 0.0 + ], + "max": [ + 0.9249999523162842, + 0.8943588733673096, + 1.4170360565185547 + ] + }, + "bounds_godot": { + "min": [ + -0.9249999523162842, + 0.0, + -0.8943588733673096 + ], + "max": [ + 0.9249999523162842, + 1.4170360565185547, + 0.8943588137626648 + ] + }, + "scale_applied": 1.1615049686592722, + "blender_version": "5.2.1 LTS", + "sha256": "7e48c0663f6cc63ef3d6d9d953d27a75452532ba57336ebd92901714ab0d6da0", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 167270 +} diff --git a/assets-source/phase4/records/e03.json b/assets-source/phase4/records/e03.json new file mode 100644 index 0000000..1798c5c --- /dev/null +++ b/assets-source/phase4/records/e03.json @@ -0,0 +1,120 @@ +{ + "id": "e03", + "name": "Nebelrest", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.9, + "footprint": 1.55, + "file": "enemy_e03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e03.blend", + "triangles": 35898, + "mesh_parts": 69, + "parts": [ + "Body_Torso", + "Body_RibL0", + "Body_RibR0", + "Body_RibL1", + "Body_RibR1", + "Body_RibL2", + "Body_RibR2", + "Body_RibL3", + "Body_RibR3", + "Body_RibL4", + "Body_RibR4", + "Head_Skull", + "Head_Face", + "Head_EyeL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "Head_EyeR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_RiftHalo" + ], + "bounds_blender": { + "min": [ + -0.5139663815498352, + -0.3523808419704437, + 0.0 + ], + "max": [ + 0.5139663815498352, + 0.3523808419704437, + 1.899999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.5139663815498352, + 0.0, + -0.3523808419704437 + ], + "max": [ + 0.5139663815498352, + 1.899999976158142, + 0.3523808419704437 + ] + }, + "scale_applied": 0.9491437054201817, + "blender_version": "5.2.1 LTS", + "sha256": "b5fb8ca2d127392886e3e820cbea85181ad4cb4c85357e61b91bc124e4a9972b", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 299628 +} diff --git a/assets-source/phase4/records/e04.json b/assets-source/phase4/records/e04.json new file mode 100644 index 0000000..44d0a21 --- /dev/null +++ b/assets-source/phase4/records/e04.json @@ -0,0 +1,161 @@ +{ + "id": "e04", + "name": "Fadenschütze", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.8, + "footprint": 1.85, + "file": "enemy_e04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e04.blend", + "triangles": 51050, + "mesh_parts": 110, + "parts": [ + "Body_Torso", + "Body_RibL0", + "Body_RibR0", + "Body_RibL1", + "Body_RibR1", + "Body_RibL2", + "Body_RibR2", + "Body_RibL3", + "Body_RibR3", + "Body_RibL4", + "Body_RibR4", + "Head_Skull", + "Head_Face", + "Head_EyeL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "Head_EyeR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_ShinGold", + "LegL_ShinEmber", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_ShinGold", + "LegR_ShinEmber", + "Weapon_Bow_1", + "Weapon_String_1", + "Weapon_Bow1", + "Weapon_String1", + "Weapon_Arrow" + ], + "bounds_blender": { + "min": [ + -0.6411548256874084, + -0.5445201396942139, + 0.0 + ], + "max": [ + 0.6411548256874084, + 0.5445201396942139, + 1.8000000715255737 + ] + }, + "bounds_godot": { + "min": [ + -0.6411548256874084, + 0.0, + -0.5445201396942139 + ], + "max": [ + 0.6411548256874084, + 1.8000000715255737, + 0.5445201396942139 + ] + }, + "scale_applied": 0.9808101893351833, + "blender_version": "5.2.1 LTS", + "sha256": "6f27424be363a48621f09b27956fc79a9697bc3d5339d10dd210ca9bf6f2da90", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 353780 +} diff --git a/assets-source/phase4/records/e05.json b/assets-source/phase4/records/e05.json new file mode 100644 index 0000000..ab39deb --- /dev/null +++ b/assets-source/phase4/records/e05.json @@ -0,0 +1,176 @@ +{ + "id": "e05", + "name": "Bruchstampfer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.0, + "footprint": 2.1, + "file": "enemy_e05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e05.blend", + "triangles": 62798, + "mesh_parts": 125, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_BruteCore", + "Body_Chest0__1", + "Body_Chest0_1", + "Body_Chest1__1", + "Body_Chest1_1", + "Body_Chest2__1", + "Body_Chest2_1", + "Body_RiftCrack", + "Body_BackSlab0", + "Body_BackSlab1", + "Body_BackSlab2", + "Body_BackSlab3", + "Head_Mask_Porcelain", + "Head_Mask_EyeSocket_1", + "Head_Mask_EyeLight_1", + "Head_Mask_EyeSocket1", + "Head_Mask_EyeLight1", + "Head_Mask_Nose", + "Head_Mask_MouthSlit0", + "Head_Mask_MouthSlit1", + "Head_Mask_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_StoneHammer", + "ArmL_Knuckle0", + "ArmL_Knuckle1", + "ArmL_Knuckle2", + "ArmL_Cuff", + "Body_ShoulderSpikeL0", + "Body_ShoulderSpikeL1", + "Body_ShoulderSpikeL2", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_StoneHammer", + "ArmR_Knuckle0", + "ArmR_Knuckle1", + "ArmR_Knuckle2", + "ArmR_Cuff", + "Body_ShoulderSpikeR0", + "Body_ShoulderSpikeR1", + "Body_ShoulderSpikeR2" + ], + "bounds_blender": { + "min": [ + -1.0383927822113037, + -0.5819846391677856, + 0.0 + ], + "max": [ + 1.0383927822113037, + 0.5819846391677856, + 2.0 + ] + }, + "bounds_godot": { + "min": [ + -1.0383927822113037, + 0.0, + -0.5819846391677856 + ], + "max": [ + 1.0383927822113037, + 2.0, + 0.5819846391677856 + ] + }, + "scale_applied": 1.1904761431709188, + "blender_version": "5.2.1 LTS", + "sha256": "c50aaa97fdc1b61cf97bed26d40416b0d28f38f159de5f661ff26cb769abf8d8", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 482828 +} diff --git a/assets-source/phase4/records/e06.json b/assets-source/phase4/records/e06.json new file mode 100644 index 0000000..c324efb --- /dev/null +++ b/assets-source/phase4/records/e06.json @@ -0,0 +1,135 @@ +{ + "id": "e06", + "name": "Knotenrufer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.0, + "footprint": 1.9, + "file": "enemy_e06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e06.blend", + "triangles": 48336, + "mesh_parts": 84, + "parts": [ + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Head_Face_Porcelain", + "Head_Face_EyeSocket_1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeLight1", + "Head_Face_Nose", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffKnot", + "Weapon_StaffHeart", + "Weapon_KnotBranch_1", + "Weapon_KnotBranch1", + "Body_HealingKnot0", + "Body_HealingKnot1", + "Body_HealingKnot2" + ], + "bounds_blender": { + "min": [ + -0.6508334875106812, + -0.38141751289367676, + 0.0 + ], + "max": [ + 0.6508334279060364, + 0.38141751289367676, + 2.000000238418579 + ] + }, + "bounds_godot": { + "min": [ + -0.6508334875106812, + 0.0, + -0.38141751289367676 + ], + "max": [ + 0.6508334279060364, + 2.000000238418579, + 0.38141751289367676 + ] + }, + "scale_applied": 1.0387229339294783, + "blender_version": "5.2.1 LTS", + "sha256": "974519186fc9259d751317a502cff848e2d126bd3cd47df37591296c46186e6f", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 432966 +} diff --git a/assets-source/phase4/records/e07.json b/assets-source/phase4/records/e07.json new file mode 100644 index 0000000..f0917e5 --- /dev/null +++ b/assets-source/phase4/records/e07.json @@ -0,0 +1,100 @@ +{ + "id": "e07", + "name": "Bruchhirsch", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.6, + "footprint": 2.5, + "file": "enemy_e07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e07.blend", + "triangles": 33800, + "mesh_parts": 49, + "parts": [ + "Body_DeerCore", + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "LegL0_Upper", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Hoof", + "LegL0_ClovenLine", + "LegL1_Upper", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Hoof", + "LegL1_ClovenLine", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_EyeL", + "LegR0_Upper", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Hoof", + "LegR0_ClovenLine", + "LegR1_Upper", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Hoof", + "LegR1_ClovenLine", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Head_AntlerR", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_EyeR", + "Head_Neck", + "Head_Skull", + "Head_Muzzle", + "Head_Nose", + "Body_Tail" + ], + "bounds_blender": { + "min": [ + -0.761934757232666, + -0.9935017824172974, + 0.0 + ], + "max": [ + 0.761934757232666, + 0.9935017824172974, + 2.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.761934757232666, + 0.0, + -0.9935017824172974 + ], + "max": [ + 0.761934757232666, + 2.5999999046325684, + 0.9935017824172974 + ] + }, + "scale_applied": 0.9961686224146542, + "blender_version": "5.2.1 LTS", + "sha256": "a293fe75a8430a89110b17e61df1b13c4a48fdacd21e3fcde7f070aded387810", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 388220 +} diff --git a/assets-source/phase4/records/e08.json b/assets-source/phase4/records/e08.json new file mode 100644 index 0000000..e69e628 --- /dev/null +++ b/assets-source/phase4/records/e08.json @@ -0,0 +1,273 @@ +{ + "id": "e08", + "name": "Riegelkoloss", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.6, + "footprint": 2.7, + "file": "enemy_e08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e08.blend", + "triangles": 81240, + "mesh_parts": 222, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowRecess2", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_Merlon0", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap3", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowRecess2", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_Merlon0", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap3", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold", + "Head_Crown_StoneKeep", + "Head_Crown_LowerCornice", + "Head_Crown_UpperCornice", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowFire0", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowFire1", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowRecess2", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel2", + "Head_Crown_Merlon0", + "Head_Crown_MerlonCap0", + "Head_Crown_Merlon1", + "Head_Crown_MerlonCap1", + "Head_Crown_Merlon2", + "Head_Crown_MerlonCap2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap3", + "Body_SpineGold", + "Body_RiftHorn_1", + "Body_RiftHorn1" + ], + "bounds_blender": { + "min": [ + -1.1929707527160645, + -0.5861989855766296, + 0.0 + ], + "max": [ + 1.1929707527160645, + 0.5861990451812744, + 2.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -1.1929707527160645, + 0.0, + -0.5861990451812744 + ], + "max": [ + 1.1929707527160645, + 2.6000001430511475, + 0.5861989855766296 + ] + }, + "scale_applied": 1.4130434526274926, + "blender_version": "5.2.1 LTS", + "sha256": "c196108262b2708200b4fee2a4a69c5c8f7551fabb90d296ce7bf482f44e4049", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 470520 +} diff --git a/assets-source/phase4/records/e09.json b/assets-source/phase4/records/e09.json new file mode 100644 index 0000000..77fcaf1 --- /dev/null +++ b/assets-source/phase4/records/e09.json @@ -0,0 +1,186 @@ +{ + "id": "e09", + "name": "Maskenrichter", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.9, + "footprint": 2.6, + "file": "enemy_e09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e09.blend", + "triangles": 57310, + "mesh_parts": 135, + "parts": [ + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Head_Face_Porcelain", + "Head_Face_EyeSocket_1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeLight1", + "Head_Face_Nose", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffKnot", + "Weapon_StaffHeart", + "Weapon_KnotBranch_1", + "Weapon_KnotBranch1", + "Body_JudgeHalo", + "Body_JudgeGlow", + "Body_CourtMask0_Porcelain", + "Body_CourtMask0_EyeSocket_1", + "Body_CourtMask0_EyeLight_1", + "Body_CourtMask0_EyeSocket1", + "Body_CourtMask0_EyeLight1", + "Body_CourtMask0_Nose", + "Body_CourtMask0_MouthSlit0", + "Body_CourtMask0_MouthSlit1", + "Body_CourtMask0_MouthSlit2", + "Body_CrownSpike0", + "Body_CourtMask1_Porcelain", + "Body_CourtMask1_EyeSocket_1", + "Body_CourtMask1_EyeLight_1", + "Body_CourtMask1_EyeSocket1", + "Body_CourtMask1_EyeLight1", + "Body_CourtMask1_Nose", + "Body_CourtMask1_MouthSlit0", + "Body_CourtMask1_MouthSlit1", + "Body_CourtMask1_MouthSlit2", + "Body_CrownSpike1", + "Body_CourtMask2_Porcelain", + "Body_CourtMask2_EyeSocket_1", + "Body_CourtMask2_EyeLight_1", + "Body_CourtMask2_EyeSocket1", + "Body_CourtMask2_EyeLight1", + "Body_CourtMask2_Nose", + "Body_CourtMask2_MouthSlit0", + "Body_CourtMask2_MouthSlit1", + "Body_CourtMask2_MouthSlit2", + "Body_CrownSpike2", + "Body_CourtMask3_Porcelain", + "Body_CourtMask3_EyeSocket_1", + "Body_CourtMask3_EyeLight_1", + "Body_CourtMask3_EyeSocket1", + "Body_CourtMask3_EyeLight1", + "Body_CourtMask3_Nose", + "Body_CourtMask3_MouthSlit0", + "Body_CourtMask3_MouthSlit1", + "Body_CourtMask3_MouthSlit2", + "Body_CrownSpike3", + "Body_CourtMask4_Porcelain", + "Body_CourtMask4_EyeSocket_1", + "Body_CourtMask4_EyeLight_1", + "Body_CourtMask4_EyeSocket1", + "Body_CourtMask4_EyeLight1", + "Body_CourtMask4_Nose", + "Body_CourtMask4_MouthSlit0", + "Body_CourtMask4_MouthSlit1", + "Body_CourtMask4_MouthSlit2", + "Body_CrownSpike4", + "Body_Chains_1", + "Body_Chains1" + ], + "bounds_blender": { + "min": [ + -0.8772106170654297, + -0.4426944851875305, + 0.0 + ], + "max": [ + 0.8772106170654297, + 0.4426945149898529, + 2.9000000953674316 + ] + }, + "bounds_godot": { + "min": [ + -0.8772106170654297, + 0.0, + -0.4426945149898529 + ], + "max": [ + 0.8772106170654297, + 2.9000000953674316, + 0.4426944851875305 + ] + }, + "scale_applied": 1.2055999949252425, + "blender_version": "5.2.1 LTS", + "sha256": "52fc2b44a0c0b9b4f343412d4c4858db9ec23adf0d6383fdfc59b8c98bb05aa9", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 441940 +} diff --git a/assets-source/phase4/records/e10.json b/assets-source/phase4/records/e10.json new file mode 100644 index 0000000..43f34e2 --- /dev/null +++ b/assets-source/phase4/records/e10.json @@ -0,0 +1,133 @@ +{ + "id": "e10", + "name": "Schlundkrone", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.9, + "footprint": 3.1, + "file": "enemy_e10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e10.blend", + "triangles": 64694, + "mesh_parts": 82, + "parts": [ + "Body_CrownCore", + "LegL0_Inner", + "LegL0_Thigh", + "LegL0_Shin", + "LegL0_Joint", + "LegL0_Claw0", + "LegL0_Claw1", + "LegL0_Claw2", + "LegL1_Inner", + "LegL1_Thigh", + "LegL1_Shin", + "LegL1_Joint", + "LegL1_Claw0", + "LegL1_Claw1", + "LegL1_Claw2", + "Body_ShellL0", + "Body_RidgeL0", + "Body_ShellL1", + "Body_RidgeL1", + "Body_ShellL2", + "Body_RidgeL2", + "Body_ShellL3", + "Body_RidgeL3", + "LegR0_Inner", + "LegR0_Thigh", + "LegR0_Shin", + "LegR0_Joint", + "LegR0_Claw0", + "LegR0_Claw1", + "LegR0_Claw2", + "LegR1_Inner", + "LegR1_Thigh", + "LegR1_Shin", + "LegR1_Joint", + "LegR1_Claw0", + "LegR1_Claw1", + "LegR1_Claw2", + "Body_ShellR0", + "Body_RidgeR0", + "Body_ShellR1", + "Body_RidgeR1", + "Body_ShellR2", + "Body_RidgeR2", + "Body_ShellR3", + "Body_RidgeR3", + "Head_MawVoid", + "Head_MawRim", + "Head_RiftThroat", + "Head_Tooth0", + "Head_Tooth1", + "Head_Tooth2", + "Head_Tooth3", + "Head_Tooth4", + "Head_Tooth5", + "Head_Tooth6", + "Head_Tooth7", + "Head_Tooth8", + "Head_Tooth9", + "Head_Tooth10", + "Head_Tooth11", + "Head_Tooth12", + "Head_Tooth13", + "Head_Brow_1", + "Head_Eye_1", + "Head_Brow1", + "Head_Eye1", + "Head_CrownBand", + "Head_CrownPoint0", + "Head_CrownGem0", + "Head_CrownPoint1", + "Head_CrownGem1", + "Head_CrownPoint2", + "Head_CrownGem2", + "Head_CrownPoint3", + "Head_CrownGem3", + "Head_CrownPoint4", + "Head_CrownGem4", + "Head_CrownPoint5", + "Head_CrownGem5", + "Head_CrownPoint6", + "Head_CrownGem6", + "Body_Tail" + ], + "bounds_blender": { + "min": [ + -1.152681827545166, + -1.2775990962982178, + 0.0 + ], + "max": [ + 1.152681827545166, + 1.2775990962982178, + 2.8999996185302734 + ] + }, + "bounds_godot": { + "min": [ + -1.152681827545166, + 0.0, + -1.2775990962982178 + ], + "max": [ + 1.152681827545166, + 2.8999996185302734, + 1.2775990962982178 + ] + }, + "scale_applied": 1.3497444874946902, + "blender_version": "5.2.1 LTS", + "sha256": "92fd4fed1e6324a5ba6adf143ae6c1e14ea022d6e63bb3bcae124326a15850d5", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 708914 +} diff --git a/assets-source/phase4/records/g01.json b/assets-source/phase4/records/g01.json new file mode 100644 index 0000000..4088286 --- /dev/null +++ b/assets-source/phase4/records/g01.json @@ -0,0 +1,182 @@ +{ + "id": "g01", + "name": "Kohlenbeißer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g01.blend", + "triangles": 79780, + "mesh_parts": 131, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_JawCavity", + "Head_MouthEmber", + "Head_BrowL", + "Head_EyeL", + "Head_CheekL", + "Head_UpperToothL0", + "Head_LowerToothL0", + "Head_UpperToothL1", + "Head_LowerToothL1", + "Head_UpperToothL2", + "Head_LowerToothL2", + "Head_UpperToothL3", + "Head_LowerToothL3", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "WeaponL_Claw0", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle0_Head", + "WeaponL_Claw1", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle1_Head", + "WeaponL_Claw2", + "ArmL_Knuckle2_Seat", + "ArmL_Knuckle2_Head", + "ArmL_ShoulderTrim", + "Head_BrowR", + "Head_EyeR", + "Head_CheekR", + "Head_UpperToothR0", + "Head_LowerToothR0", + "Head_UpperToothR1", + "Head_LowerToothR1", + "Head_UpperToothR2", + "Head_LowerToothR2", + "Head_UpperToothR3", + "Head_LowerToothR3", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "WeaponR_Claw0", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle0_Head", + "WeaponR_Claw1", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle1_Head", + "WeaponR_Claw2", + "ArmR_Knuckle2_Seat", + "ArmR_Knuckle2_Head", + "ArmR_ShoulderTrim", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Head_Chin" + ], + "bounds_blender": { + "min": [ + -0.7924438118934631, + -0.4473014771938324, + 0.0 + ], + "max": [ + 0.7924438118934631, + 0.44730144739151, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.7924438118934631, + 0.0, + -0.44730144739151 + ], + "max": [ + 0.7924438118934631, + 1.350000023841858, + 0.4473014771938324 + ] + }, + "scale_applied": 0.9629486449307071, + "blender_version": "5.2.1 LTS", + "sha256": "b51f8bb5188c950f4f9cecde7125b225d7ba5cbe103d89335047dd97a2873c1d", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 641050 +} diff --git a/assets-source/phase4/records/g02.json b/assets-source/phase4/records/g02.json new file mode 100644 index 0000000..c9f6b62 --- /dev/null +++ b/assets-source/phase4/records/g02.json @@ -0,0 +1,184 @@ +{ + "id": "g02", + "name": "Schlackenklaue", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g02.blend", + "triangles": 75624, + "mesh_parts": 133, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_JawCavity", + "Head_MouthEmber", + "Head_BrowL", + "Head_EyeL", + "Head_CheekL", + "Head_UpperToothL0", + "Head_LowerToothL0", + "Head_UpperToothL1", + "Head_LowerToothL1", + "Head_UpperToothL2", + "Head_LowerToothL2", + "Head_UpperToothL3", + "Head_LowerToothL3", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "WeaponL_Claw0", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle0_Head", + "WeaponL_Claw1", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle1_Head", + "WeaponL_Claw2", + "ArmL_Knuckle2_Seat", + "ArmL_Knuckle2_Head", + "ArmL_ShoulderTrim", + "Head_BrowR", + "Head_EyeR", + "Head_CheekR", + "Head_UpperToothR0", + "Head_LowerToothR0", + "Head_UpperToothR1", + "Head_LowerToothR1", + "Head_UpperToothR2", + "Head_LowerToothR2", + "Head_UpperToothR3", + "Head_LowerToothR3", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "WeaponR_Claw0", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle0_Head", + "WeaponR_Claw1", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle1_Head", + "WeaponR_Claw2", + "ArmR_Knuckle2_Seat", + "ArmR_Knuckle2_Head", + "ArmR_ShoulderTrim", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Head_Chin" + ], + "bounds_blender": { + "min": [ + -0.8933426141738892, + -0.48825082182884216, + 0.0 + ], + "max": [ + 0.8933426141738892, + 0.4882507920265198, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.8933426141738892, + 0.0, + -0.4882507920265198 + ], + "max": [ + 0.8933426141738892, + 1.5, + 0.48825082182884216 + ] + }, + "scale_applied": 1.0511041683008056, + "blender_version": "5.2.1 LTS", + "sha256": "b008047744d5e82ed47ca50a61ca633fd38599446669079be9677b020e411486", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 549234 +} diff --git a/assets-source/phase4/records/g03.json b/assets-source/phase4/records/g03.json new file mode 100644 index 0000000..6ec2440 --- /dev/null +++ b/assets-source/phase4/records/g03.json @@ -0,0 +1,170 @@ +{ + "id": "g03", + "name": "Schlackenwacht", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g03.blend", + "triangles": 67232, + "mesh_parts": 119, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold" + ], + "bounds_blender": { + "min": [ + -0.8888235092163086, + -0.43674787878990173, + 0.0 + ], + "max": [ + 0.8888235092163086, + 0.4367479383945465, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.8888235092163086, + 0.0, + -0.4367479383945465 + ], + "max": [ + 0.8888235092163086, + 1.350000023841858, + 0.43674787878990173 + ] + }, + "scale_applied": 1.0527888124172442, + "blender_version": "5.2.1 LTS", + "sha256": "4a6e16b9ecd40f3ab9176c0fbe37cc52c27b9da16406732daa1587e37e135fa0", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 565982 +} diff --git a/assets-source/phase4/records/g04.json b/assets-source/phase4/records/g04.json new file mode 100644 index 0000000..90fcc80 --- /dev/null +++ b/assets-source/phase4/records/g04.json @@ -0,0 +1,271 @@ +{ + "id": "g04", + "name": "Basaltbastion", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g04.blend", + "triangles": 80764, + "mesh_parts": 220, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowRecess2", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_Merlon0", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap3", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowRecess2", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_Merlon0", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap3", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold", + "Head_Crown_StoneKeep", + "Head_Crown_LowerCornice", + "Head_Crown_UpperCornice", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowFire0", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowFire1", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowRecess2", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel2", + "Head_Crown_Merlon0", + "Head_Crown_MerlonCap0", + "Head_Crown_Merlon1", + "Head_Crown_MerlonCap1", + "Head_Crown_Merlon2", + "Head_Crown_MerlonCap2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap3", + "Body_SpineGold" + ], + "bounds_blender": { + "min": [ + -0.7569541335105896, + -0.37195026874542236, + 0.0 + ], + "max": [ + 0.7569541335105896, + 0.37195026874542236, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.7569541335105896, + 0.0, + -0.37195026874542236 + ], + "max": [ + 0.7569541335105896, + 1.5, + 0.37195026874542236 + ] + }, + "scale_applied": 0.8965928946707251, + "blender_version": "5.2.1 LTS", + "sha256": "9f9a963c80b3b79817eee4ea9e75af3819ca1a204e17d9bdb0072f3b5f60ab7c", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 470044 +} diff --git a/assets-source/phase4/records/g05.json b/assets-source/phase4/records/g05.json new file mode 100644 index 0000000..d24ab42 --- /dev/null +++ b/assets-source/phase4/records/g05.json @@ -0,0 +1,169 @@ +{ + "id": "g05", + "name": "Funkenlanze", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_g05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g05.blend", + "triangles": 54710, + "mesh_parts": 118, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_ShinGold", + "LegL_ShinEmber", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_ShinGold", + "LegR_ShinEmber", + "Body_Spine", + "Body_CuirassL", + "Body_ChestStoneL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_ShoulderFin", + "Body_CuirassR", + "Body_ChestStoneR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_ShoulderFin", + "Body_EmberHeart", + "Head_Neck", + "Head_Helmet", + "Head_Visor", + "Head_Crest", + "Weapon_LanceShaft", + "Weapon_LanceEmber", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceCollar10", + "Weapon_SpearHead", + "Weapon_SpearEdge_1", + "Weapon_SpearEdge1" + ], + "bounds_blender": { + "min": [ + -0.7841845750808716, + -0.22315844893455505, + 0.0 + ], + "max": [ + 0.7841845750808716, + 0.22315844893455505, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.7841845750808716, + 0.0, + -0.22315844893455505 + ], + "max": [ + 0.7841845750808716, + 1.4500000476837158, + 0.22315844893455505 + ] + }, + "scale_applied": 0.8333333287659276, + "blender_version": "5.2.1 LTS", + "sha256": "f21ee9e96ae65f986a6f51ce950ec1885bb7da7f72f58e232f37d9255ca3e49a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 382610 +} diff --git a/assets-source/phase4/records/g06.json b/assets-source/phase4/records/g06.json new file mode 100644 index 0000000..74f719c --- /dev/null +++ b/assets-source/phase4/records/g06.json @@ -0,0 +1,136 @@ +{ + "id": "g06", + "name": "Glasballiste", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_g06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g06.blend", + "triangles": 38036, + "mesh_parts": 85, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_Gearbox", + "Body_CrankL", + "Body_CrankInsetL", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Weapon_RailL", + "Weapon_RailTrimL", + "Weapon_GlassLimbL", + "Weapon_LimbEdgeL", + "Weapon_DrawCableL", + "Weapon_LimbClampL", + "Body_CrankR", + "Body_CrankInsetR", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Weapon_RailR", + "Weapon_RailTrimR", + "Weapon_GlassLimbR", + "Weapon_LimbEdgeR", + "Weapon_DrawCableR", + "Weapon_LimbClampR", + "Weapon_RearHousing", + "Weapon_RearTrim", + "Weapon_CentralBolt", + "Weapon_BoltHead", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5" + ], + "bounds_blender": { + "min": [ + -0.9249999523162842, + -0.8653658628463745, + 0.0 + ], + "max": [ + 0.9249999523162842, + 0.8653659224510193, + 1.3369946479797363 + ] + }, + "bounds_godot": { + "min": [ + -0.9249999523162842, + 0.0, + -0.8653659224510193 + ], + "max": [ + 0.9249999523162842, + 1.3369946479797363, + 0.8653658628463745 + ] + }, + "scale_applied": 1.0914242850007518, + "blender_version": "5.2.1 LTS", + "sha256": "6480508f062b8610cfbcc24b0067d25a80b7404de29a12c49a99fd6b5a379cee", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 261386 +} diff --git a/assets-source/phase4/records/g07.json b/assets-source/phase4/records/g07.json new file mode 100644 index 0000000..fe6c5eb --- /dev/null +++ b/assets-source/phase4/records/g07.json @@ -0,0 +1,179 @@ +{ + "id": "g07", + "name": "Aschenwerfer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g07.blend", + "triangles": 81492, + "mesh_parts": 128, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LowerCore", + "Body_MortarBore", + "Body_MortarStave0", + "Body_RimClasp0", + "Body_MortarStave1", + "Body_RimClasp1", + "Body_MortarStave2", + "Body_RimClasp2", + "Body_MortarStave3", + "Body_RimClasp3", + "Body_MortarStave4", + "Body_RimClasp4", + "Body_MortarStave5", + "Body_RimClasp5", + "Body_MortarStave6", + "Body_RimClasp6", + "Body_MortarStave7", + "Body_RimClasp7", + "Body_MortarStave8", + "Body_RimClasp8", + "Body_MortarStave9", + "Body_RimClasp9", + "Body_MortarStave10", + "Body_RimClasp10", + "Body_MortarStave11", + "Body_RimClasp11", + "Body_MortarLip", + "Body_MortarBelt", + "Weapon_LavaPool", + "Weapon_EmberBoulder", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil" + ], + "bounds_blender": { + "min": [ + -0.821897029876709, + -0.6239631772041321, + 0.0 + ], + "max": [ + 0.8218969702720642, + 0.6239631772041321, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.821897029876709, + 0.0, + -0.6239631772041321 + ], + "max": [ + 0.8218969702720642, + 1.350000023841858, + 0.6239631772041321 + ] + }, + "scale_applied": 1.136363671028108, + "blender_version": "5.2.1 LTS", + "sha256": "e8112a137032ca74e5d50714f49ee3a318e37e3323572ed6d5d153a38c726a88", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 687762 +} diff --git a/assets-source/phase4/records/g08.json b/assets-source/phase4/records/g08.json new file mode 100644 index 0000000..ff1b573 --- /dev/null +++ b/assets-source/phase4/records/g08.json @@ -0,0 +1,174 @@ +{ + "id": "g08", + "name": "Kraterrufer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g08.blend", + "triangles": 77130, + "mesh_parts": 123, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LowerCore", + "Body_MortarBore", + "Body_MortarStave0", + "Body_RimClasp0", + "Body_MortarStave1", + "Body_RimClasp1", + "Body_MortarStave2", + "Body_RimClasp2", + "Body_MortarStave3", + "Body_RimClasp3", + "Body_MortarStave4", + "Body_RimClasp4", + "Body_MortarStave5", + "Body_RimClasp5", + "Body_MortarStave6", + "Body_RimClasp6", + "Body_MortarStave7", + "Body_RimClasp7", + "Body_MortarStave8", + "Body_RimClasp8", + "Body_MortarStave9", + "Body_RimClasp9", + "Body_MortarStave10", + "Body_RimClasp10", + "Body_MortarStave11", + "Body_RimClasp11", + "Body_MortarLip", + "Body_MortarBelt", + "Weapon_LavaPool", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil" + ], + "bounds_blender": { + "min": [ + -0.9132189750671387, + -0.745126485824585, + 0.0 + ], + "max": [ + 0.9132189154624939, + 0.745126485824585, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.9132189750671387, + 0.0, + -0.745126485824585 + ], + "max": [ + 0.9132189154624939, + 1.5, + 0.745126485824585 + ] + }, + "scale_applied": 1.2626263011423422, + "blender_version": "5.2.1 LTS", + "sha256": "1f7a3c940c5798ee73c7f2c2b91fbf2531f5446b85d0d3bd6f4554b6a0124cb6", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 683400 +} diff --git a/assets-source/phase4/records/g09.json b/assets-source/phase4/records/g09.json new file mode 100644 index 0000000..e6accdf --- /dev/null +++ b/assets-source/phase4/records/g09.json @@ -0,0 +1,224 @@ +{ + "id": "g09", + "name": "Herdhüter", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_g09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g09.blend", + "triangles": 84568, + "mesh_parts": 173, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_HearthBack", + "Body_OvenDark", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_ArchStone10", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Head_Chimney", + "Head_ChimneyRecess", + "Head_ChimneyCap", + "Weapon_HearthBowl", + "Weapon_BowlRim", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11" + ], + "bounds_blender": { + "min": [ + -0.6256327033042908, + -0.5413227677345276, + 0.0 + ], + "max": [ + 0.6256327033042908, + 0.5413227081298828, + 1.4500001668930054 + ] + }, + "bounds_godot": { + "min": [ + -0.6256327033042908, + 0.0, + -0.5413227081298828 + ], + "max": [ + 0.6256327033042908, + 1.4500001668930054, + 0.5413227677345276 + ] + }, + "scale_applied": 0.9206349624437739, + "blender_version": "5.2.1 LTS", + "sha256": "0b65843813708495ea96349bc5dab83c932e389f47327ef1892b7fb4e9481f97", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 685558 +} diff --git a/assets-source/phase4/records/g10.json b/assets-source/phase4/records/g10.json new file mode 100644 index 0000000..52ddcfd --- /dev/null +++ b/assets-source/phase4/records/g10.json @@ -0,0 +1,274 @@ +{ + "id": "g10", + "name": "Sonnenesse", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_g10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g10.blend", + "triangles": 96706, + "mesh_parts": 223, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_HearthBack", + "Body_OvenDark", + "Body_SunSocket", + "Body_SunFrame", + "Body_SunHeart", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_MantleL", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_TabardL", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_MantleR", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_TabardR", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Weapon_HearthBowl", + "Weapon_BowlRim", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Body_SolarStream" + ], + "bounds_blender": { + "min": [ + -0.6629917025566101, + -0.58647620677948, + 0.0 + ], + "max": [ + 0.6629916429519653, + 0.5864762663841248, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.6629917025566101, + 0.0, + -0.5864762663841248 + ], + "max": [ + 0.6629916429519653, + 1.600000023841858, + 0.58647620677948 + ] + }, + "scale_applied": 0.9756097646074449, + "blender_version": "5.2.1 LTS", + "sha256": "ed5a7c265e25d592a367b3bc8a152ee6ace6aabb2964b6f563b4509967829715", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 697696 +} diff --git a/assets-source/phase4/records/m01.json b/assets-source/phase4/records/m01.json new file mode 100644 index 0000000..0588852 --- /dev/null +++ b/assets-source/phase4/records/m01.json @@ -0,0 +1,89 @@ +{ + "id": "m01", + "name": "Kesselwicht", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m01.glb", + "resource_path": "res://assets/models/unit_m01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m01.blend", + "triangles": 1284, + "mesh_parts": 42, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_RoundKettle", + "Body_Belt", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye_1", + "Head_Eye1", + "Head_Mouth", + "Body_PressureGauge", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_Chimney", + "Body_ChimneyLip", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Fist", + "ArmL_Cuff", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Fist", + "ArmR_Cuff" + ], + "bounds_blender": { + "min": [ + -0.5699462890625, + -0.3646690249443054, + 0.0 + ], + "max": [ + 0.5699462890625, + 0.3646690249443054, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.5699462890625, + 0.0, + -0.3646690249443054 + ], + "max": [ + 0.5699462890625, + 1.350000023841858, + 0.3646690249443054 + ] + }, + "scale_applied": 0.966010707083804, + "blender_version": "5.2.1 LTS", + "sha256": "dfa98866025c5801cc6aff2ef8273dfe393a397623f641046c4babade8516df1", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m02.json b/assets-source/phase4/records/m02.json new file mode 100644 index 0000000..ec66f40 --- /dev/null +++ b/assets-source/phase4/records/m02.json @@ -0,0 +1,99 @@ +{ + "id": "m02", + "name": "Druckhüter", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m02.glb", + "resource_path": "res://assets/models/unit_m02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m02.blend", + "triangles": 1360, + "mesh_parts": 52, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_HeavyChest", + "Body_CeramicChest_Rim", + "Body_CeramicChest_Face", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_PressureTankL", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_ValveStemL", + "Body_ValveWheelL", + "Body_PressureTankR", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemR", + "Body_ValveWheelR", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Fist", + "ArmL_Cuff", + "ArmL_Pauldron", + "ArmL_Shield_Rim", + "ArmL_Shield_Face", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Fist", + "ArmR_Cuff", + "ArmR_Pauldron", + "ArmR_Shield_Rim", + "ArmR_Shield_Face" + ], + "bounds_blender": { + "min": [ + -0.6054872274398804, + -0.2990065813064575, + 0.0 + ], + "max": [ + 0.6054872274398804, + 0.2990066111087799, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.6054872274398804, + 0.0, + -0.2990066111087799 + ], + "max": [ + 0.6054872274398804, + 1.5, + 0.2990065813064575 + ] + }, + "scale_applied": 0.9460737926177909, + "blender_version": "5.2.1 LTS", + "sha256": "8aeb014358b502dccdf0a8202214b8456e43e04c38333c6218eb7cbb0864bb2b", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m03.json b/assets-source/phase4/records/m03.json new file mode 100644 index 0000000..48f77ec --- /dev/null +++ b/assets-source/phase4/records/m03.json @@ -0,0 +1,90 @@ +{ + "id": "m03", + "name": "Scherschreiter", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m03.glb", + "resource_path": "res://assets/models/unit_m03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m03.blend", + "triangles": 932, + "mesh_parts": 43, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "ArmL0_Rod", + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "ArmR0_Rod", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ], + "bounds_blender": { + "min": [ + -0.7748520374298096, + -0.14178994297981262, + 0.0 + ], + "max": [ + 0.7748520374298096, + 0.14178994297981262, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.7748520374298096, + 0.0, + -0.14178994297981262 + ], + "max": [ + 0.7748520374298096, + 1.350000023841858, + 0.14178994297981262 + ] + }, + "scale_applied": 0.7988165410007994, + "blender_version": "5.2.1 LTS", + "sha256": "8efdd35dfe2c6194f7b9705a0324d66ff260d9936f9099b6b1f81790c03831af", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m04.json b/assets-source/phase4/records/m04.json new file mode 100644 index 0000000..61e1374 --- /dev/null +++ b/assets-source/phase4/records/m04.json @@ -0,0 +1,107 @@ +{ + "id": "m04", + "name": "Sechsklingler", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m04.glb", + "resource_path": "res://assets/models/unit_m04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m04.blend", + "triangles": 1398, + "mesh_parts": 60, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "ArmL0_Rod", + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "WeaponL0_Blade0", + "ArmL1_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "WeaponL1_Blade0", + "ArmL2_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "WeaponL2_Blade0", + "ArmR0_Rod", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "WeaponR0_Blade0", + "ArmR1_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "WeaponR1_Blade0", + "ArmR2_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "WeaponR2_Blade0" + ], + "bounds_blender": { + "min": [ + -0.821377158164978, + -0.15030355751514435, + 0.0 + ], + "max": [ + 0.821377158164978, + 0.15030354261398315, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.821377158164978, + 0.0, + -0.15030354261398315 + ], + "max": [ + 0.821377158164978, + 1.5, + 0.15030355751514435 + ] + }, + "scale_applied": 0.8467805123236263, + "blender_version": "5.2.1 LTS", + "sha256": "a55e114218bee93ee40dc90a368414bef0fae6d4580f032f72687565ec9d9bc8", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m05.json b/assets-source/phase4/records/m05.json new file mode 100644 index 0000000..2335f5e --- /dev/null +++ b/assets-source/phase4/records/m05.json @@ -0,0 +1,99 @@ +{ + "id": "m05", + "name": "Bolzenknecht", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_m05.glb", + "resource_path": "res://assets/models/unit_m05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m05.blend", + "triangles": 1148, + "mesh_parts": 52, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "Head_Scope", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_String_1", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1" + ], + "bounds_blender": { + "min": [ + -0.3836592435836792, + -0.40458109974861145, + 0.0 + ], + "max": [ + 0.3836592435836792, + 0.40458106994628906, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.3836592435836792, + 0.0, + -0.40458106994628906 + ], + "max": [ + 0.3836592435836792, + 1.4499999284744263, + 0.40458109974861145 + ] + }, + "scale_applied": 0.8479531974579839, + "blender_version": "5.2.1 LTS", + "sha256": "0d5f61b02d29d09c807a6d6c07341620a4f1a4bee0d300391cbd4a9a0f5cfbb5", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m06.json b/assets-source/phase4/records/m06.json new file mode 100644 index 0000000..db527e7 --- /dev/null +++ b/assets-source/phase4/records/m06.json @@ -0,0 +1,113 @@ +{ + "id": "m06", + "name": "Linienmeister", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_m06.glb", + "resource_path": "res://assets/models/unit_m06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m06.blend", + "triangles": 1432, + "mesh_parts": 66, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_ThighArmor", + "Leg2_Greave", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg2_AnkleGold", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_ThighArmor", + "Leg3_Greave", + "Leg3_Toe0", + "Leg3_Toe1", + "Leg3_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_String_1", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1" + ], + "bounds_blender": { + "min": [ + -0.6025153398513794, + -0.6586429476737976, + 0.0 + ], + "max": [ + 0.6025153994560242, + 0.6586429476737976, + 1.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -0.6025153398513794, + 0.0, + -0.6586429476737976 + ], + "max": [ + 0.6025153994560242, + 1.6000001430511475, + 0.6586429476737976 + ] + }, + "scale_applied": 0.9356724937467409, + "blender_version": "5.2.1 LTS", + "sha256": "489574f3e4614bcd75e3486fa8fd6f578195f2f4d6455c86936ad8a8f6d696a6", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m07.json b/assets-source/phase4/records/m07.json new file mode 100644 index 0000000..406adc3 --- /dev/null +++ b/assets-source/phase4/records/m07.json @@ -0,0 +1,74 @@ +{ + "id": "m07", + "name": "Klangkolben", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m07.glb", + "resource_path": "res://assets/models/unit_m07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m07.blend", + "triangles": 740, + "mesh_parts": 27, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_SiegeChassis", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_ResonatorHousing0", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston", + "Body_HousingLatch0__1", + "Body_HousingLatch0_1" + ], + "bounds_blender": { + "min": [ + -0.4213939905166626, + -0.4975554347038269, + 0.0 + ], + "max": [ + 0.4213939905166626, + 0.4975554347038269, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.4213939905166626, + 0.0, + -0.4975554347038269 + ], + "max": [ + 0.4213939905166626, + 1.3499999046325684, + 0.4975554347038269 + ] + }, + "scale_applied": 1.015419270119985, + "blender_version": "5.2.1 LTS", + "sha256": "44b7ea1ec7290f639fa15b985223f03dd92992684ee0257197bafd9663dae643", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m08.json b/assets-source/phase4/records/m08.json new file mode 100644 index 0000000..8526e92 --- /dev/null +++ b/assets-source/phase4/records/m08.json @@ -0,0 +1,97 @@ +{ + "id": "m08", + "name": "Resonanzramme", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m08.glb", + "resource_path": "res://assets/models/unit_m08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m08.blend", + "triangles": 1316, + "mesh_parts": 50, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_ThighArmor", + "Leg2_Greave", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg2_AnkleGold", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_ThighArmor", + "Leg3_Greave", + "Leg3_Toe0", + "Leg3_Toe1", + "Leg3_AnkleGold", + "Body_SiegeChassis", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_ResonatorHousing0", + "Weapon_ImpactDisc0", + "Weapon_DiscPiston0", + "Body_HousingLatch0__1", + "Body_HousingLatch0_1", + "Body_ResonatorHousing1", + "Weapon_ImpactDisc1", + "Weapon_DiscPiston1", + "Body_HousingLatch1__1", + "Body_HousingLatch1_1" + ], + "bounds_blender": { + "min": [ + -0.7338443994522095, + -0.5147383809089661, + 0.0 + ], + "max": [ + 0.7338443994522095, + 0.5147383809089661, + 1.4999998807907104 + ] + }, + "bounds_godot": { + "min": [ + -0.7338443994522095, + 0.0, + -0.5147383809089661 + ], + "max": [ + 0.7338443994522095, + 1.4999998807907104, + 0.5147383809089661 + ] + }, + "scale_applied": 1.0952902191196374, + "blender_version": "5.2.1 LTS", + "sha256": "3601cc62c2245e84d58d472b444434fe962851fdc3d663df6572623218063484", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m09.json b/assets-source/phase4/records/m09.json new file mode 100644 index 0000000..c804739 --- /dev/null +++ b/assets-source/phase4/records/m09.json @@ -0,0 +1,98 @@ +{ + "id": "m09", + "name": "Taktspindel", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_m09.glb", + "resource_path": "res://assets/models/unit_m09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m09.blend", + "triangles": 1160, + "mesh_parts": 51, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye_1", + "Head_Eye1", + "Head_Mouth", + "Body_PendulumStem", + "Body_PendulumBob", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Palm", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "Weapon_Baton", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Palm", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2" + ], + "bounds_blender": { + "min": [ + -0.5013101696968079, + -0.14016570150852203, + 0.0 + ], + "max": [ + 0.5013101696968079, + 0.14016570150852203, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.5013101696968079, + 0.0, + -0.14016570150852203 + ], + "max": [ + 0.5013101696968079, + 1.4500000476837158, + 0.14016570150852203 + ] + }, + "scale_applied": 0.7896659202045064, + "blender_version": "5.2.1 LTS", + "sha256": "11d8104ffbbd31954fd87b23e2901220c9794fd459808491e9ab2e5ac36b3179", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/m10.json b/assets-source/phase4/records/m10.json new file mode 100644 index 0000000..aa059b6 --- /dev/null +++ b/assets-source/phase4/records/m10.json @@ -0,0 +1,96 @@ +{ + "id": "m10", + "name": "Taktprälat", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_m10.glb", + "resource_path": "res://assets/models/unit_m10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m10.blend", + "triangles": 946, + "mesh_parts": 49, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Coat", + "Body_CreamStoleL", + "Body_CoatGoldL", + "Body_CreamStoleR", + "Body_CoatGoldR", + "Body_PendulumOpening", + "Body_PendulumStem", + "Body_PendulumBob", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Palm", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "Weapon_Baton", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Palm", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2" + ], + "bounds_blender": { + "min": [ + -0.5444233417510986, + -0.4287889897823334, + 0.0 + ], + "max": [ + 0.5444233417510986, + 0.4287889897823334, + 1.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -0.5444233417510986, + 0.0, + -0.4287889897823334 + ], + "max": [ + 0.5444233417510986, + 1.6000001430511475, + 0.4287889897823334 + ] + }, + "scale_applied": 0.8575779752970936, + "blender_version": "5.2.1 LTS", + "sha256": "43a36780c0ced0869b976bec4fe1423ad7ef14f5b7f68a720da72ad44c28970e", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/map_lane_segment.json b/assets-source/phase4/records/map_lane_segment.json new file mode 100644 index 0000000..46e8bce --- /dev/null +++ b/assets-source/phase4/records/map_lane_segment.json @@ -0,0 +1,96 @@ +{ + "id": "map_lane_segment", + "name": "Lane-Segment", + "faction": "terrain", + "palette": "terrain", + "role": "lane", + "upgraded": false, + "height": 0, + "file": "map_lane_segment.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/map_lane_segment.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/map_lane_segment.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/map_lane_segment.blend", + "triangles": 10700, + "mesh_parts": 45, + "parts": [ + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LRetainingLip", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_RRetainingLip", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeStone_1_0", + "Body_EdgeCap_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeCap_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeCap_1_2", + "Body_EdgeStone_1_3", + "Body_EdgeCap_1_3", + "Body_LightRecess_1_0", + "Body_LightGlass_1_0", + "Body_LightRecess_1_1", + "Body_LightGlass_1_1", + "Body_EdgeStone1_0", + "Body_EdgeCap1_0", + "Body_EdgeStone1_1", + "Body_EdgeCap1_1", + "Body_EdgeStone1_2", + "Body_EdgeCap1_2", + "Body_EdgeStone1_3", + "Body_EdgeCap1_3", + "Body_LightRecess1_0", + "Body_LightGlass1_0", + "Body_LightRecess1_1", + "Body_LightGlass1_1" + ], + "bounds_blender": { + "min": [ + -6.688923358917236, + -2.0, + -0.3499999940395355 + ], + "max": [ + 6.688923358917236, + 2.0, + 0.3935000002384186 + ] + }, + "bounds_godot": { + "min": [ + -6.688923358917236, + -0.3499999940395355, + -2.0 + ], + "max": [ + 6.688923358917236, + 0.3935000002384186, + 2.0 + ] + }, + "scale_applied": 1.0, + "blender_version": "5.2.1 LTS", + "sha256": "32886ae71fc72a188ec72c3931f177d1192043574d31c96da47f6ebfdcb880cc", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n01.json b/assets-source/phase4/records/n01.json new file mode 100644 index 0000000..d86b5f0 --- /dev/null +++ b/assets-source/phase4/records/n01.json @@ -0,0 +1,63 @@ +{ + "id": "n01", + "name": "Saummaske", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n01.glb", + "resource_path": "res://assets/models/unit_n01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n01.blend", + "triangles": 1132, + "mesh_parts": 16, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "ArmL", + "WeaponL_Claw", + "ArmR", + "WeaponR_Claw" + ], + "bounds_blender": { + "min": [ + -0.44347620010375977, + -0.19742706418037415, + 0.0 + ], + "max": [ + 0.44347620010375977, + 0.19742707908153534, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.44347620010375977, + 0.0, + -0.19742707908153534 + ], + "max": [ + 0.44347620010375977, + 1.3499999046325684, + 0.19742706418037415 + ] + }, + "scale_applied": 0.855141167579754, + "blender_version": "5.2.1 LTS", + "sha256": "b374d208cc0541a73800b27802507287f349df4b4400f4e56cbeb8461b3579a5", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n02.json b/assets-source/phase4/records/n02.json new file mode 100644 index 0000000..fecbd10 --- /dev/null +++ b/assets-source/phase4/records/n02.json @@ -0,0 +1,65 @@ +{ + "id": "n02", + "name": "Grenzmaske", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n02.glb", + "resource_path": "res://assets/models/unit_n02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n02.blend", + "triangles": 1156, + "mesh_parts": 18, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay" + ], + "bounds_blender": { + "min": [ + -0.6379754543304443, + -0.21133150160312653, + 0.0 + ], + "max": [ + 0.6379754543304443, + 0.21133150160312653, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.6379754543304443, + 0.0, + -0.21133150160312653 + ], + "max": [ + 0.6379754543304443, + 1.5, + 0.21133150160312653 + ] + }, + "scale_applied": 0.9153671897165055, + "blender_version": "5.2.1 LTS", + "sha256": "fc1a7d3b2d46a9dbbb8834aa1f51189a8389368bfd662f71120d63fcbf2b55a2", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n03.json b/assets-source/phase4/records/n03.json new file mode 100644 index 0000000..32574a9 --- /dev/null +++ b/assets-source/phase4/records/n03.json @@ -0,0 +1,60 @@ +{ + "id": "n03", + "name": "Fadentänzer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n03.glb", + "resource_path": "res://assets/models/unit_n03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n03.blend", + "triangles": 934, + "mesh_parts": 13, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "WeaponL_Sickle", + "ArmR", + "WeaponR_Sickle" + ], + "bounds_blender": { + "min": [ + -0.4779128134250641, + -0.16183501482009888, + 0.0 + ], + "max": [ + 0.4779128432273865, + 0.16183499991893768, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.4779128134250641, + 0.0, + -0.16183499991893768 + ], + "max": [ + 0.4779128432273865, + 1.3499999046325684, + 0.16183501482009888 + ] + }, + "scale_applied": 0.772007890355257, + "blender_version": "5.2.1 LTS", + "sha256": "cffec8cc2a300291d8d14431fafc4225e8f7a517709922f1dd8c98d27e7dd086", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n04.json b/assets-source/phase4/records/n04.json new file mode 100644 index 0000000..1ce9fab --- /dev/null +++ b/assets-source/phase4/records/n04.json @@ -0,0 +1,64 @@ +{ + "id": "n04", + "name": "Saumzertrenner", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n04.glb", + "resource_path": "res://assets/models/unit_n04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n04.blend", + "triangles": 1360, + "mesh_parts": 17, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "ArmR", + "Weapon_ShearPivot", + "Weapon_ShearLower", + "Weapon_ShearLoopLower", + "Weapon_ShearUpper", + "Weapon_ShearLoopUpper", + "Head_CrescentCrown" + ], + "bounds_blender": { + "min": [ + -0.5531443357467651, + -0.19565065205097198, + 0.0 + ], + "max": [ + 0.5531443357467651, + 0.19565066695213318, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5531443357467651, + 0.0, + -0.19565066695213318 + ], + "max": [ + 0.5531443357467651, + 1.5, + 0.19565065205097198 + ] + }, + "scale_applied": 0.8571428571428571, + "blender_version": "5.2.1 LTS", + "sha256": "7796469cefde7029f31a1af60fe298ffe8cd00c1d6653d73a8d748a8814f1bd6", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n05.json b/assets-source/phase4/records/n05.json new file mode 100644 index 0000000..8894b05 --- /dev/null +++ b/assets-source/phase4/records/n05.json @@ -0,0 +1,60 @@ +{ + "id": "n05", + "name": "Fernflüsterer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_n05.glb", + "resource_path": "res://assets/models/unit_n05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n05.blend", + "triangles": 1118, + "mesh_parts": 13, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip", + "ArmL", + "ArmR" + ], + "bounds_blender": { + "min": [ + -0.4346340298652649, + -0.2853573262691498, + 0.0 + ], + "max": [ + 0.4346340000629425, + 0.2853573262691498, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.4346340298652649, + 0.0, + -0.2853573262691498 + ], + "max": [ + 0.4346340000629425, + 1.4499999284744263, + 0.2853573262691498 + ] + }, + "scale_applied": 0.8387870445874587, + "blender_version": "5.2.1 LTS", + "sha256": "590fcb19ee024cbf64eb8db4c570ff6afeacf393b8c58788b2192b011797e9b4", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n06.json b/assets-source/phase4/records/n06.json new file mode 100644 index 0000000..dcfedf2 --- /dev/null +++ b/assets-source/phase4/records/n06.json @@ -0,0 +1,64 @@ +{ + "id": "n06", + "name": "Fernrufer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_n06.glb", + "resource_path": "res://assets/models/unit_n06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n06.blend", + "triangles": 1498, + "mesh_parts": 17, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "Weapon_HornArchL", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "ArmR", + "Weapon_HornArchR", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ], + "bounds_blender": { + "min": [ + -0.8301005959510803, + -0.3197994828224182, + 0.0 + ], + "max": [ + 0.8301005959510803, + 0.3197995126247406, + 1.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.8301005959510803, + 0.0, + -0.3197995126247406 + ], + "max": [ + 0.8301005959510803, + 1.5999999046325684, + 0.3197994828224182 + ] + }, + "scale_applied": 0.9255581181654716, + "blender_version": "5.2.1 LTS", + "sha256": "590e012f1b09ada25aa5ec48ff78eb60bd1bf3facd6c0b8cebd2a12c13142e58", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n07.json b/assets-source/phase4/records/n07.json new file mode 100644 index 0000000..a54765a --- /dev/null +++ b/assets-source/phase4/records/n07.json @@ -0,0 +1,62 @@ +{ + "id": "n07", + "name": "Glockenschlepper", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n07.glb", + "resource_path": "res://assets/models/unit_n07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n07.blend", + "triangles": 1274, + "mesh_parts": 15, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Weapon_HangingBell", + "Weapon_BellRim", + "Weapon_ClapperStem", + "Weapon_Clapper", + "ArmL", + "ArmR" + ], + "bounds_blender": { + "min": [ + -0.35533595085144043, + -0.37528085708618164, + 0.0 + ], + "max": [ + 0.35533595085144043, + 0.37528085708618164, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.35533595085144043, + 0.0, + -0.37528085708618164 + ], + "max": [ + 0.35533595085144043, + 1.3499999046325684, + 0.37528085708618164 + ] + }, + "scale_applied": 0.7382346585301032, + "blender_version": "5.2.1 LTS", + "sha256": "8ff3d936bb7329f12177a45e1a7df5324e40e0d49a4d0ecdf49d5da75fd153e7", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n08.json b/assets-source/phase4/records/n08.json new file mode 100644 index 0000000..6540653 --- /dev/null +++ b/assets-source/phase4/records/n08.json @@ -0,0 +1,65 @@ +{ + "id": "n08", + "name": "Hohlgeläut", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n08.glb", + "resource_path": "res://assets/models/unit_n08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n08.blend", + "triangles": 1482, + "mesh_parts": 18, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Body_CathedralShell", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Weapon_ClapperChain", + "Weapon_Clapper", + "Body_ArchMask", + "Body_ArchMask_Eye_1", + "Body_ArchMask_Eye1", + "Head_SpireL", + "ArmL_Sickle", + "Head_SpireR", + "ArmR_Sickle", + "Head_CentralSpire" + ], + "bounds_blender": { + "min": [ + -0.5439560413360596, + -0.4138086140155792, + 0.0 + ], + "max": [ + 0.5439560413360596, + 0.4138086140155792, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5439560413360596, + 0.0, + -0.4138086140155792 + ], + "max": [ + 0.5439560413360596, + 1.5, + 0.4138086140155792 + ] + }, + "scale_applied": 0.8241758004232191, + "blender_version": "5.2.1 LTS", + "sha256": "d4da0c654034e57a8faecd7d54ab94914cf61881fdad8b0a667cc8d4119d244e", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n09.json b/assets-source/phase4/records/n09.json new file mode 100644 index 0000000..bb79e4a --- /dev/null +++ b/assets-source/phase4/records/n09.json @@ -0,0 +1,71 @@ +{ + "id": "n09", + "name": "Maskenkantor", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_n09.glb", + "resource_path": "res://assets/models/unit_n09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n09.blend", + "triangles": 1314, + "mesh_parts": 24, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Head_SingingMouth", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_ChoirHorn0__1", + "Head_ChoirHorn0_1" + ], + "bounds_blender": { + "min": [ + -0.543777346611023, + -0.1794917732477188, + 0.0 + ], + "max": [ + 0.543777346611023, + 0.17949174344539642, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.543777346611023, + 0.0, + -0.17949174344539642 + ], + "max": [ + 0.543777346611023, + 1.4500000476837158, + 0.1794917732477188 + ] + }, + "scale_applied": 0.8198173476403533, + "blender_version": "5.2.1 LTS", + "sha256": "af2e461d6b23464a8c3c4d956e0b4ae9a18892f27eaf882973b0a10a8c05fa46", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/n10.json b/assets-source/phase4/records/n10.json new file mode 100644 index 0000000..12487b6 --- /dev/null +++ b/assets-source/phase4/records/n10.json @@ -0,0 +1,87 @@ +{ + "id": "n10", + "name": "Vielstimmenkantor", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_n10.glb", + "resource_path": "res://assets/models/unit_n10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n10.blend", + "triangles": 1734, + "mesh_parts": 40, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Head_SingingMouth", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_ChoirHorn0__1", + "Head_ChoirHorn0_1", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Mouth", + "Head_ChoirWisp1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn1_1", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp2", + "Head_ChoirHorn2__1", + "Head_ChoirHorn2_1", + "Head_GreatHorn_1", + "Head_GreatHorn1" + ], + "bounds_blender": { + "min": [ + -0.5053644776344299, + -0.17586638033390045, + 0.0 + ], + "max": [ + 0.5053644776344299, + 0.17586638033390045, + 1.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5053644776344299, + 0.0, + -0.17586638033390045 + ], + "max": [ + 0.5053644776344299, + 1.5999999046325684, + 0.17586638033390045 + ] + }, + "scale_applied": 0.7619047965051922, + "blender_version": "5.2.1 LTS", + "sha256": "8c723f7bcb3e363fdf42ee2aed2109e1c9e8a0a532b4b207f5fdf1b557474651", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/s01.json b/assets-source/phase4/records/s01.json new file mode 100644 index 0000000..db61b2c --- /dev/null +++ b/assets-source/phase4/records/s01.json @@ -0,0 +1,83 @@ +{ + "id": "s01", + "name": "Nadelspäher", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s01.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s01.blend", + "triangles": 10340, + "mesh_parts": 34, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "Body_LeatherCuirass", + "Head_HoodBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_HoodRim", + "Body_Scarf", + "Body_DiagonalBelt", + "Body_SplitCoat_1", + "Body_TornScarf_1", + "Body_SplitCoat1", + "Body_TornScarf1", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "Weapon_CrossbowStock", + "Weapon_Bow_1", + "Weapon_String_1", + "Weapon_Bow1", + "Weapon_String1", + "Weapon_Bolt" + ], + "bounds_blender": { + "min": [ + -0.4479508697986603, + -0.4116958975791931, + 0.0 + ], + "max": [ + 0.44795089960098267, + 0.4116959273815155, + 1.399999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.4479508697986603, + 0.0, + -0.4116959273815155 + ], + "max": [ + 0.44795089960098267, + 1.399999976158142, + 0.4116958975791931 + ] + }, + "scale_applied": 0.8589844747132427, + "blender_version": "5.2.1 LTS", + "sha256": "af4b60706912d9004b420d37da0d19e0324ffe1d1d182d22214e93a212814df4", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/s02.json b/assets-source/phase4/records/s02.json new file mode 100644 index 0000000..f27a81a --- /dev/null +++ b/assets-source/phase4/records/s02.json @@ -0,0 +1,87 @@ +{ + "id": "s02", + "name": "Rostschieber", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s02.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s02.blend", + "triangles": 12040, + "mesh_parts": 38, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Strap", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Strap", + "Body_Armor_Rim", + "Body_Armor_Face", + "Body_Belt", + "Body_Tabard", + "Head_HelmetBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "Weapon_TowerShield_Rim", + "Weapon_TowerShield_Face", + "Weapon_ShieldSpine", + "Weapon_ShieldBoss", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_Corner10_4", + "Weapon_Corner11_16" + ], + "bounds_blender": { + "min": [ + -0.484041690826416, + -0.37111228704452515, + 0.0 + ], + "max": [ + 0.484041690826416, + 0.37111228704452515, + 1.3999998569488525 + ] + }, + "bounds_godot": { + "min": [ + -0.484041690826416, + 0.0, + -0.37111228704452515 + ], + "max": [ + 0.484041690826416, + 1.3999998569488525, + 0.37111228704452515 + ] + }, + "scale_applied": 0.8869464095328802, + "blender_version": "5.2.1 LTS", + "sha256": "64bf431dfd07516aabc01b29529ec6a3e6250a8c122feb254bed75aa0df021a2", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/s03.json b/assets-source/phase4/records/s03.json new file mode 100644 index 0000000..2f2a5de --- /dev/null +++ b/assets-source/phase4/records/s03.json @@ -0,0 +1,68 @@ +{ + "id": "s03", + "name": "Dunstsänger", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s03.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s03.blend", + "triangles": 7832, + "mesh_parts": 19, + "parts": [ + "Body_LongRobe", + "Head_HoodBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_HoodRim", + "Body_Scarf", + "Body_CreamStole_1", + "Body_RaggedCloak_1", + "Body_CreamStole1", + "Body_RaggedCloak1", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "Weapon_Trumpet" + ], + "bounds_blender": { + "min": [ + -0.592510461807251, + -0.41805312037467957, + 0.0 + ], + "max": [ + 0.592510461807251, + 0.41805312037467957, + 1.399999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.592510461807251, + 0.0, + -0.41805312037467957 + ], + "max": [ + 0.592510461807251, + 1.399999976158142, + 0.41805312037467957 + ] + }, + "scale_applied": 0.8434590980140588, + "blender_version": "5.2.1 LTS", + "sha256": "35c287e7a3885528bc3e69272abacb9cfc5d516b183e323570ad38462234e87c", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/s04.json b/assets-source/phase4/records/s04.json new file mode 100644 index 0000000..9aa4e8e --- /dev/null +++ b/assets-source/phase4/records/s04.json @@ -0,0 +1,84 @@ +{ + "id": "s04", + "name": "Keilbrecher", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s04.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s04.blend", + "triangles": 10458, + "mesh_parts": 35, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Strap", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Strap", + "Body_Armor_Rim", + "Body_Armor_Face", + "Body_Belt", + "Body_Tabard", + "Head_HelmetBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "Weapon_Haft", + "Weapon_Head", + "Weapon_Wedge", + "Weapon_TriangleRim", + "Weapon_TriangleInset" + ], + "bounds_blender": { + "min": [ + -0.638360857963562, + -0.3721802830696106, + 0.0 + ], + "max": [ + 0.638360857963562, + 0.37218034267425537, + 1.3999998569488525 + ] + }, + "bounds_godot": { + "min": [ + -0.638360857963562, + 0.0, + -0.37218034267425537 + ], + "max": [ + 0.638360857963562, + 1.3999998569488525, + 0.3721802830696106 + ] + }, + "scale_applied": 0.8869464095328802, + "blender_version": "5.2.1 LTS", + "sha256": "a160e00f5823e54e93b00b12378357f6e3e20f254ca48890450ebdf3dd1541b7", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/s05.json b/assets-source/phase4/records/s05.json new file mode 100644 index 0000000..2ab982f --- /dev/null +++ b/assets-source/phase4/records/s05.json @@ -0,0 +1,80 @@ +{ + "id": "s05", + "name": "Risszehrer", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.5499999999999998, + "footprint": 1.85, + "file": "unit_s05.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s05.blend", + "triangles": 10440, + "mesh_parts": 31, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "Body_HollowRib_1", + "Body_RiftEdge_1", + "Body_TornCloth_1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_RiftEdge1", + "Body_TornCloth1", + "Body_HipRag1", + "Head_FacelessHelm", + "Head_MintCrack", + "Head_Antler_1", + "Head_InnerHorn_1", + "Head_Antler1", + "Head_InnerHorn1", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "Weapon_RiftOrb", + "Weapon_RiftLight" + ], + "bounds_blender": { + "min": [ + -0.4230315685272217, + -0.1786629855632782, + 0.0 + ], + "max": [ + 0.4230315387248993, + 0.178662970662117, + 1.5500001907348633 + ] + }, + "bounds_godot": { + "min": [ + -0.4230315685272217, + 0.0, + -0.178662970662117 + ], + "max": [ + 0.4230315387248993, + 1.5500001907348633, + 0.1786629855632782 + ] + }, + "scale_applied": 0.8728638592455813, + "blender_version": "5.2.1 LTS", + "sha256": "b01c1c71782aff1fcf988aa9032bbdcd4c50e6dc96de62f3bed9f949f4355bef", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w01.json b/assets-source/phase4/records/w01.json new file mode 100644 index 0000000..9c097f1 --- /dev/null +++ b/assets-source/phase4/records/w01.json @@ -0,0 +1,217 @@ +{ + "id": "w01", + "name": "Dornhopser", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w01.blend", + "triangles": 61376, + "offline_sculpt_parts": 18, + "offline_render_triangles": 695666, + "mesh_parts": 166, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_MossHeart", + "Body_WovenBark0", + "Body_WovenBark0_Grain0", + "Body_WovenBark0_Grain1", + "Body_WovenBark1", + "Body_WovenBark1_Grain0", + "Body_WovenBark1_Grain1", + "Body_WovenBark2", + "Body_WovenBark2_Grain0", + "Body_WovenBark2_Grain1", + "Body_WovenBark3", + "Body_WovenBark3_Grain0", + "Body_WovenBark3_Grain1", + "Body_WovenBark4", + "Body_WovenBark4_Grain0", + "Body_WovenBark4_Grain1", + "Body_WovenBark5", + "Body_WovenBark5_Grain0", + "Body_WovenBark5_Grain1", + "Body_ShoulderLeaf0", + "Body_ShoulderLeaf0_Midrib", + "Body_ShoulderLeaf0_Vein0__1", + "Body_ShoulderLeaf0_Vein0_1", + "Body_ShoulderLeaf0_Vein1__1", + "Body_ShoulderLeaf0_Vein1_1", + "Body_ShoulderLeaf0_Vein2__1", + "Body_ShoulderLeaf0_Vein2_1", + "Body_ShoulderLeaf1", + "Body_ShoulderLeaf1_Midrib", + "Body_ShoulderLeaf1_Vein0__1", + "Body_ShoulderLeaf1_Vein0_1", + "Body_ShoulderLeaf1_Vein1__1", + "Body_ShoulderLeaf1_Vein1_1", + "Body_ShoulderLeaf1_Vein2__1", + "Body_ShoulderLeaf1_Vein2_1", + "Body_ShoulderLeaf2", + "Body_ShoulderLeaf2_Midrib", + "Body_ShoulderLeaf2_Vein0__1", + "Body_ShoulderLeaf2_Vein0_1", + "Body_ShoulderLeaf2_Vein1__1", + "Body_ShoulderLeaf2_Vein1_1", + "Body_ShoulderLeaf2_Vein2__1", + "Body_ShoulderLeaf2_Vein2_1", + "Body_ShoulderLeaf3", + "Body_ShoulderLeaf3_Midrib", + "Body_ShoulderLeaf3_Vein0__1", + "Body_ShoulderLeaf3_Vein0_1", + "Body_ShoulderLeaf3_Vein1__1", + "Body_ShoulderLeaf3_Vein1_1", + "Body_ShoulderLeaf3_Vein2__1", + "Body_ShoulderLeaf3_Vein2_1", + "Body_Bark0", + "Body_Bark0_Fissure0", + "Body_Bark0_Fissure1", + "Body_Bark0_Fissure2", + "Body_Bark0_Fissure3", + "Body_Thorn0", + "Body_Bark1", + "Body_Bark1_Fissure0", + "Body_Bark1_Fissure1", + "Body_Bark1_Fissure2", + "Body_Bark1_Fissure3", + "Body_Thorn1", + "Body_Bark2", + "Body_Bark2_Fissure0", + "Body_Bark2_Fissure1", + "Body_Bark2_Fissure2", + "Body_Bark2_Fissure3", + "Body_Thorn2", + "Body_Bark3", + "Body_Bark3_Fissure0", + "Body_Bark3_Fissure1", + "Body_Bark3_Fissure2", + "Body_Bark3_Fissure3", + "Body_Thorn3", + "Body_Bark4", + "Body_Bark4_Fissure0", + "Body_Bark4_Fissure1", + "Body_Bark4_Fissure2", + "Body_Bark4_Fissure3", + "Body_Thorn4", + "Body_Bark5", + "Body_Bark5_Fissure0", + "Body_Bark5_Fissure1", + "Body_Bark5_Fissure2", + "Body_Bark5_Fissure3", + "Body_Thorn5", + "Body_Bark6", + "Body_Bark6_Fissure0", + "Body_Bark6_Fissure1", + "Body_Bark6_Fissure2", + "Body_Bark6_Fissure3", + "Body_Thorn6", + "Body_Bark7", + "Body_Bark7_Fissure0", + "Body_Bark7_Fissure1", + "Body_Bark7_Fissure2", + "Body_Bark7_Fissure3", + "Body_Thorn7", + "Body_Bark8", + "Body_Bark8_Fissure0", + "Body_Bark8_Fissure1", + "Body_Bark8_Fissure2", + "Body_Bark8_Fissure3", + "Body_Thorn8", + "Head_EyeShadow", + "Head_Eye_1", + "Head_Sprout_1", + "Head_Sprout_1_Midrib", + "Head_Sprout_1_Vein0__1", + "Head_Sprout_1_Vein0_1", + "Head_Sprout_1_Vein1__1", + "Head_Sprout_1_Vein1_1", + "Head_Sprout_1_Vein2__1", + "Head_Sprout_1_Vein2_1", + "Head_Eye1", + "Head_Sprout1", + "Head_Sprout1_Midrib", + "Head_Sprout1_Vein0__1", + "Head_Sprout1_Vein0_1", + "Head_Sprout1_Vein1__1", + "Head_Sprout1_Vein1_1", + "Head_Sprout1_Vein2__1", + "Head_Sprout1_Vein2_1", + "Body_Blossom_Petal0", + "Body_Blossom_Petal1", + "Body_Blossom_Petal2", + "Body_Blossom_Petal3", + "Body_Blossom_Petal4", + "Body_Blossom_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5014952421188354, + -0.43660610914230347, + 0.0 + ], + "max": [ + 0.5014951825141907, + 0.43660610914230347, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5014952421188354, + 0.0, + -0.43660610914230347 + ], + "max": [ + 0.5014951825141907, + 1.3499999046325684, + 0.43660610914230347 + ] + }, + "scale_applied": 0.922440014955025, + "blender_version": "5.2.1 LTS", + "sha256": "68ff8429b46cfb249fd02496e8cf64016c73f5f8df9761f21c83beb12c09b1c3", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w02.json b/assets-source/phase4/records/w02.json new file mode 100644 index 0000000..e85993e --- /dev/null +++ b/assets-source/phase4/records/w02.json @@ -0,0 +1,288 @@ +{ + "id": "w02", + "name": "Rankenschnapper", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w02.blend", + "triangles": 78020, + "offline_sculpt_parts": 15, + "offline_render_triangles": 810680, + "mesh_parts": 237, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_JawDark", + "Head_Upper_Jaw", + "Head_Upper_Lip0", + "Head_Upper_Lip1", + "Head_Upper_Lip2", + "Head_Upper_Fang0", + "Head_Upper_Fang1", + "Head_Upper_Fang2", + "Head_Upper_Fang3", + "Head_Upper_Fang4", + "Head_Upper_Fang5", + "Head_Upper_Fang6", + "Head_Upper_Fang7", + "Head_Upper_Fang8", + "Head_Lower_Jaw", + "Head_Lower_Lip0", + "Head_Lower_Lip1", + "Head_Lower_Lip2", + "Head_Lower_Fang0", + "Head_Lower_Fang1", + "Head_Lower_Fang2", + "Head_Lower_Fang3", + "Head_Lower_Fang4", + "Head_Lower_Fang5", + "Head_Lower_Fang6", + "Head_Lower_Fang7", + "Head_Lower_Fang8", + "Head_JawLeaf0", + "Head_JawLeaf0_Midrib", + "Head_JawLeaf0_Vein0__1", + "Head_JawLeaf0_Vein0_1", + "Head_JawLeaf0_Vein1__1", + "Head_JawLeaf0_Vein1_1", + "Head_JawLeaf0_Vein2__1", + "Head_JawLeaf0_Vein2_1", + "Head_JawLeaf1", + "Head_JawLeaf1_Midrib", + "Head_JawLeaf1_Vein0__1", + "Head_JawLeaf1_Vein0_1", + "Head_JawLeaf1_Vein1__1", + "Head_JawLeaf1_Vein1_1", + "Head_JawLeaf1_Vein2__1", + "Head_JawLeaf1_Vein2_1", + "Head_JawLeaf2", + "Head_JawLeaf2_Midrib", + "Head_JawLeaf2_Vein0__1", + "Head_JawLeaf2_Vein0_1", + "Head_JawLeaf2_Vein1__1", + "Head_JawLeaf2_Vein1_1", + "Head_JawLeaf2_Vein2__1", + "Head_JawLeaf2_Vein2_1", + "Head_JawLeaf3", + "Head_JawLeaf3_Midrib", + "Head_JawLeaf3_Vein0__1", + "Head_JawLeaf3_Vein0_1", + "Head_JawLeaf3_Vein1__1", + "Head_JawLeaf3_Vein1_1", + "Head_JawLeaf3_Vein2__1", + "Head_JawLeaf3_Vein2_1", + "Head_JawLeaf4", + "Head_JawLeaf4_Midrib", + "Head_JawLeaf4_Vein0__1", + "Head_JawLeaf4_Vein0_1", + "Head_JawLeaf4_Vein1__1", + "Head_JawLeaf4_Vein1_1", + "Head_JawLeaf4_Vein2__1", + "Head_JawLeaf4_Vein2_1", + "Head_JawLeaf5", + "Head_JawLeaf5_Midrib", + "Head_JawLeaf5_Vein0__1", + "Head_JawLeaf5_Vein0_1", + "Head_JawLeaf5_Vein1__1", + "Head_JawLeaf5_Vein1_1", + "Head_JawLeaf5_Vein2__1", + "Head_JawLeaf5_Vein2_1", + "Head_JawFlower_Petal0", + "Head_JawFlower_Petal1", + "Head_JawFlower_Petal2", + "Head_JawFlower_Petal3", + "Head_JawFlower_Petal4", + "Head_JawFlower_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5706138610839844, + -0.6263821721076965, + 0.0 + ], + "max": [ + 0.5706138610839844, + 0.6263822317123413, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5706138610839844, + 0.0, + -0.6263822317123413 + ], + "max": [ + 0.5706138610839844, + 1.5, + 0.6263821721076965 + ] + }, + "scale_applied": 1.1419287722959226, + "blender_version": "5.2.1 LTS", + "sha256": "e5aecc90518c172f4d05b6f4e337dbf698ca055a62242bf610347cbf64681390", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w03.json b/assets-source/phase4/records/w03.json new file mode 100644 index 0000000..ec26349 --- /dev/null +++ b/assets-source/phase4/records/w03.json @@ -0,0 +1,431 @@ +{ + "id": "w03", + "name": "Korkrücken", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w03.blend", + "triangles": 84786, + "offline_sculpt_parts": 18, + "offline_render_triangles": 782076, + "mesh_parts": 380, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_InnerMoss", + "Body_Cork0_0", + "Body_Cork0_0_Fissure0", + "Body_Cork0_0_Fissure1", + "Body_Cork0_0_Fissure2", + "Body_Cork0_0_Fissure3", + "Body_Cork0_1", + "Body_Cork0_1_Fissure0", + "Body_Cork0_1_Fissure1", + "Body_Cork0_1_Fissure2", + "Body_Cork0_1_Fissure3", + "Body_Cork0_2", + "Body_Cork0_2_Fissure0", + "Body_Cork0_2_Fissure1", + "Body_Cork0_2_Fissure2", + "Body_Cork0_2_Fissure3", + "Body_Cork0_3", + "Body_Cork0_3_Fissure0", + "Body_Cork0_3_Fissure1", + "Body_Cork0_3_Fissure2", + "Body_Cork0_3_Fissure3", + "Body_Cork0_4", + "Body_Cork0_4_Fissure0", + "Body_Cork0_4_Fissure1", + "Body_Cork0_4_Fissure2", + "Body_Cork0_4_Fissure3", + "Body_Cork0_5", + "Body_Cork0_5_Fissure0", + "Body_Cork0_5_Fissure1", + "Body_Cork0_5_Fissure2", + "Body_Cork0_5_Fissure3", + "Body_Cork0_6", + "Body_Cork0_6_Fissure0", + "Body_Cork0_6_Fissure1", + "Body_Cork0_6_Fissure2", + "Body_Cork0_6_Fissure3", + "Body_Cork1_0", + "Body_Cork1_0_Fissure0", + "Body_Cork1_0_Fissure1", + "Body_Cork1_0_Fissure2", + "Body_Cork1_0_Fissure3", + "Body_Cork1_1", + "Body_Cork1_1_Fissure0", + "Body_Cork1_1_Fissure1", + "Body_Cork1_1_Fissure2", + "Body_Cork1_1_Fissure3", + "Body_Cork1_2", + "Body_Cork1_2_Fissure0", + "Body_Cork1_2_Fissure1", + "Body_Cork1_2_Fissure2", + "Body_Cork1_2_Fissure3", + "Body_Cork1_3", + "Body_Cork1_3_Fissure0", + "Body_Cork1_3_Fissure1", + "Body_Cork1_3_Fissure2", + "Body_Cork1_3_Fissure3", + "Body_Cork1_4", + "Body_Cork1_4_Fissure0", + "Body_Cork1_4_Fissure1", + "Body_Cork1_4_Fissure2", + "Body_Cork1_4_Fissure3", + "Body_Cork1_5", + "Body_Cork1_5_Fissure0", + "Body_Cork1_5_Fissure1", + "Body_Cork1_5_Fissure2", + "Body_Cork1_5_Fissure3", + "Body_Cork1_6", + "Body_Cork1_6_Fissure0", + "Body_Cork1_6_Fissure1", + "Body_Cork1_6_Fissure2", + "Body_Cork1_6_Fissure3", + "Body_Cork2_0", + "Body_Cork2_0_Fissure0", + "Body_Cork2_0_Fissure1", + "Body_Cork2_0_Fissure2", + "Body_Cork2_0_Fissure3", + "Body_Cork2_1", + "Body_Cork2_1_Fissure0", + "Body_Cork2_1_Fissure1", + "Body_Cork2_1_Fissure2", + "Body_Cork2_1_Fissure3", + "Body_Cork2_2", + "Body_Cork2_2_Fissure0", + "Body_Cork2_2_Fissure1", + "Body_Cork2_2_Fissure2", + "Body_Cork2_2_Fissure3", + "Body_Cork2_3", + "Body_Cork2_3_Fissure0", + "Body_Cork2_3_Fissure1", + "Body_Cork2_3_Fissure2", + "Body_Cork2_3_Fissure3", + "Body_Cork2_4", + "Body_Cork2_4_Fissure0", + "Body_Cork2_4_Fissure1", + "Body_Cork2_4_Fissure2", + "Body_Cork2_4_Fissure3", + "Body_Cork2_5", + "Body_Cork2_5_Fissure0", + "Body_Cork2_5_Fissure1", + "Body_Cork2_5_Fissure2", + "Body_Cork2_5_Fissure3", + "Body_Cork2_6", + "Body_Cork2_6_Fissure0", + "Body_Cork2_6_Fissure1", + "Body_Cork2_6_Fissure2", + "Body_Cork2_6_Fissure3", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen" + ], + "bounds_blender": { + "min": [ + -0.48796892166137695, + -0.4879722595214844, + 0.0 + ], + "max": [ + 0.48796892166137695, + 0.4879722595214844, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.48796892166137695, + 0.0, + -0.4879722595214844 + ], + "max": [ + 0.48796892166137695, + 1.350000023841858, + 0.4879722595214844 + ] + }, + "scale_applied": 0.9001111644704809, + "blender_version": "5.2.1 LTS", + "sha256": "bf032894b7094d8dbcc164da190952aef8f467069c23956f39fe59bb905f491b", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w04.json b/assets-source/phase4/records/w04.json new file mode 100644 index 0000000..9e6865e --- /dev/null +++ b/assets-source/phase4/records/w04.json @@ -0,0 +1,590 @@ +{ + "id": "w04", + "name": "Ringborke", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w04.blend", + "triangles": 134530, + "offline_sculpt_parts": 18, + "offline_render_triangles": 872260, + "mesh_parts": 539, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_InnerMoss", + "Body_OverlappingBark0_0", + "Body_OverlappingBark0_0_Fissure0", + "Body_OverlappingBark0_0_Fissure1", + "Body_OverlappingBark0_0_Fissure2", + "Body_OverlappingBark0_0_Fissure3", + "Body_OverlappingBark0_1", + "Body_OverlappingBark0_1_Fissure0", + "Body_OverlappingBark0_1_Fissure1", + "Body_OverlappingBark0_1_Fissure2", + "Body_OverlappingBark0_1_Fissure3", + "Body_OverlappingBark0_2", + "Body_OverlappingBark0_2_Fissure0", + "Body_OverlappingBark0_2_Fissure1", + "Body_OverlappingBark0_2_Fissure2", + "Body_OverlappingBark0_2_Fissure3", + "Body_OverlappingBark0_3", + "Body_OverlappingBark0_3_Fissure0", + "Body_OverlappingBark0_3_Fissure1", + "Body_OverlappingBark0_3_Fissure2", + "Body_OverlappingBark0_3_Fissure3", + "Body_OverlappingBark0_4", + "Body_OverlappingBark0_4_Fissure0", + "Body_OverlappingBark0_4_Fissure1", + "Body_OverlappingBark0_4_Fissure2", + "Body_OverlappingBark0_4_Fissure3", + "Body_OverlappingBark0_5", + "Body_OverlappingBark0_5_Fissure0", + "Body_OverlappingBark0_5_Fissure1", + "Body_OverlappingBark0_5_Fissure2", + "Body_OverlappingBark0_5_Fissure3", + "Body_OverlappingBark0_6", + "Body_OverlappingBark0_6_Fissure0", + "Body_OverlappingBark0_6_Fissure1", + "Body_OverlappingBark0_6_Fissure2", + "Body_OverlappingBark0_6_Fissure3", + "Body_OverlappingBark0_7", + "Body_OverlappingBark0_7_Fissure0", + "Body_OverlappingBark0_7_Fissure1", + "Body_OverlappingBark0_7_Fissure2", + "Body_OverlappingBark0_7_Fissure3", + "Body_OverlappingBark1_0", + "Body_OverlappingBark1_0_Fissure0", + "Body_OverlappingBark1_0_Fissure1", + "Body_OverlappingBark1_0_Fissure2", + "Body_OverlappingBark1_0_Fissure3", + "Body_OverlappingBark1_1", + "Body_OverlappingBark1_1_Fissure0", + "Body_OverlappingBark1_1_Fissure1", + "Body_OverlappingBark1_1_Fissure2", + "Body_OverlappingBark1_1_Fissure3", + "Body_OverlappingBark1_2", + "Body_OverlappingBark1_2_Fissure0", + "Body_OverlappingBark1_2_Fissure1", + "Body_OverlappingBark1_2_Fissure2", + "Body_OverlappingBark1_2_Fissure3", + "Body_OverlappingBark1_3", + "Body_OverlappingBark1_3_Fissure0", + "Body_OverlappingBark1_3_Fissure1", + "Body_OverlappingBark1_3_Fissure2", + "Body_OverlappingBark1_3_Fissure3", + "Body_OverlappingBark1_4", + "Body_OverlappingBark1_4_Fissure0", + "Body_OverlappingBark1_4_Fissure1", + "Body_OverlappingBark1_4_Fissure2", + "Body_OverlappingBark1_4_Fissure3", + "Body_OverlappingBark1_5", + "Body_OverlappingBark1_5_Fissure0", + "Body_OverlappingBark1_5_Fissure1", + "Body_OverlappingBark1_5_Fissure2", + "Body_OverlappingBark1_5_Fissure3", + "Body_OverlappingBark1_6", + "Body_OverlappingBark1_6_Fissure0", + "Body_OverlappingBark1_6_Fissure1", + "Body_OverlappingBark1_6_Fissure2", + "Body_OverlappingBark1_6_Fissure3", + "Body_OverlappingBark1_7", + "Body_OverlappingBark1_7_Fissure0", + "Body_OverlappingBark1_7_Fissure1", + "Body_OverlappingBark1_7_Fissure2", + "Body_OverlappingBark1_7_Fissure3", + "Body_OverlappingBark2_0", + "Body_OverlappingBark2_0_Fissure0", + "Body_OverlappingBark2_0_Fissure1", + "Body_OverlappingBark2_0_Fissure2", + "Body_OverlappingBark2_0_Fissure3", + "Body_OverlappingBark2_1", + "Body_OverlappingBark2_1_Fissure0", + "Body_OverlappingBark2_1_Fissure1", + "Body_OverlappingBark2_1_Fissure2", + "Body_OverlappingBark2_1_Fissure3", + "Body_OverlappingBark2_2", + "Body_OverlappingBark2_2_Fissure0", + "Body_OverlappingBark2_2_Fissure1", + "Body_OverlappingBark2_2_Fissure2", + "Body_OverlappingBark2_2_Fissure3", + "Body_OverlappingBark2_3", + "Body_OverlappingBark2_3_Fissure0", + "Body_OverlappingBark2_3_Fissure1", + "Body_OverlappingBark2_3_Fissure2", + "Body_OverlappingBark2_3_Fissure3", + "Body_OverlappingBark2_4", + "Body_OverlappingBark2_4_Fissure0", + "Body_OverlappingBark2_4_Fissure1", + "Body_OverlappingBark2_4_Fissure2", + "Body_OverlappingBark2_4_Fissure3", + "Body_OverlappingBark2_5", + "Body_OverlappingBark2_5_Fissure0", + "Body_OverlappingBark2_5_Fissure1", + "Body_OverlappingBark2_5_Fissure2", + "Body_OverlappingBark2_5_Fissure3", + "Body_OverlappingBark2_6", + "Body_OverlappingBark2_6_Fissure0", + "Body_OverlappingBark2_6_Fissure1", + "Body_OverlappingBark2_6_Fissure2", + "Body_OverlappingBark2_6_Fissure3", + "Body_OverlappingBark2_7", + "Body_OverlappingBark2_7_Fissure0", + "Body_OverlappingBark2_7_Fissure1", + "Body_OverlappingBark2_7_Fissure2", + "Body_OverlappingBark2_7_Fissure3", + "Body_Log0_Bark", + "Body_Log0_Cut", + "Body_Log0_Growth0", + "Body_Log0_Growth1", + "Body_Log0_Growth2", + "Body_Log0_Growth3", + "Body_Log0_Growth4", + "Body_Log0_Growth5", + "Body_Log0_RoughEdge0", + "Body_Log0_RoughEdge1", + "Body_Log0_RoughEdge2", + "Body_Log0_RoughEdge3", + "Body_Log0_RoughEdge4", + "Body_Log0_RoughEdge5", + "Body_Log0_RoughEdge6", + "Body_Log0_RoughEdge7", + "Body_Log0_RoughEdge8", + "Body_Log0_RoughEdge9", + "Body_Log0_RoughEdge10", + "Body_Log0_RoughEdge11", + "Body_Log0_RoughEdge12", + "Body_Log0_Split0", + "Body_Log0_Split1", + "Body_Log0_Split2", + "Body_Log1_Bark", + "Body_Log1_Cut", + "Body_Log1_Growth0", + "Body_Log1_Growth1", + "Body_Log1_Growth2", + "Body_Log1_Growth3", + "Body_Log1_Growth4", + "Body_Log1_Growth5", + "Body_Log1_RoughEdge0", + "Body_Log1_RoughEdge1", + "Body_Log1_RoughEdge2", + "Body_Log1_RoughEdge3", + "Body_Log1_RoughEdge4", + "Body_Log1_RoughEdge5", + "Body_Log1_RoughEdge6", + "Body_Log1_RoughEdge7", + "Body_Log1_RoughEdge8", + "Body_Log1_RoughEdge9", + "Body_Log1_RoughEdge10", + "Body_Log1_RoughEdge11", + "Body_Log1_RoughEdge12", + "Body_Log1_Split0", + "Body_Log1_Split1", + "Body_Log1_Split2", + "Body_Log2_Bark", + "Body_Log2_Cut", + "Body_Log2_Growth0", + "Body_Log2_Growth1", + "Body_Log2_Growth2", + "Body_Log2_Growth3", + "Body_Log2_Growth4", + "Body_Log2_Growth5", + "Body_Log2_RoughEdge0", + "Body_Log2_RoughEdge1", + "Body_Log2_RoughEdge2", + "Body_Log2_RoughEdge3", + "Body_Log2_RoughEdge4", + "Body_Log2_RoughEdge5", + "Body_Log2_RoughEdge6", + "Body_Log2_RoughEdge7", + "Body_Log2_RoughEdge8", + "Body_Log2_RoughEdge9", + "Body_Log2_RoughEdge10", + "Body_Log2_RoughEdge11", + "Body_Log2_RoughEdge12", + "Body_Log2_Split0", + "Body_Log2_Split1", + "Body_Log2_Split2", + "Body_Log3_Bark", + "Body_Log3_Cut", + "Body_Log3_Growth0", + "Body_Log3_Growth1", + "Body_Log3_Growth2", + "Body_Log3_Growth3", + "Body_Log3_Growth4", + "Body_Log3_Growth5", + "Body_Log3_RoughEdge0", + "Body_Log3_RoughEdge1", + "Body_Log3_RoughEdge2", + "Body_Log3_RoughEdge3", + "Body_Log3_RoughEdge4", + "Body_Log3_RoughEdge5", + "Body_Log3_RoughEdge6", + "Body_Log3_RoughEdge7", + "Body_Log3_RoughEdge8", + "Body_Log3_RoughEdge9", + "Body_Log3_RoughEdge10", + "Body_Log3_RoughEdge11", + "Body_Log3_RoughEdge12", + "Body_Log3_Split0", + "Body_Log3_Split1", + "Body_Log3_Split2", + "Body_Log4_Bark", + "Body_Log4_Cut", + "Body_Log4_Growth0", + "Body_Log4_Growth1", + "Body_Log4_Growth2", + "Body_Log4_Growth3", + "Body_Log4_Growth4", + "Body_Log4_Growth5", + "Body_Log4_RoughEdge0", + "Body_Log4_RoughEdge1", + "Body_Log4_RoughEdge2", + "Body_Log4_RoughEdge3", + "Body_Log4_RoughEdge4", + "Body_Log4_RoughEdge5", + "Body_Log4_RoughEdge6", + "Body_Log4_RoughEdge7", + "Body_Log4_RoughEdge8", + "Body_Log4_RoughEdge9", + "Body_Log4_RoughEdge10", + "Body_Log4_RoughEdge11", + "Body_Log4_RoughEdge12", + "Body_Log4_Split0", + "Body_Log4_Split1", + "Body_Log4_Split2", + "Body_Log5_Bark", + "Body_Log5_Cut", + "Body_Log5_Growth0", + "Body_Log5_Growth1", + "Body_Log5_Growth2", + "Body_Log5_Growth3", + "Body_Log5_Growth4", + "Body_Log5_Growth5", + "Body_Log5_RoughEdge0", + "Body_Log5_RoughEdge1", + "Body_Log5_RoughEdge2", + "Body_Log5_RoughEdge3", + "Body_Log5_RoughEdge4", + "Body_Log5_RoughEdge5", + "Body_Log5_RoughEdge6", + "Body_Log5_RoughEdge7", + "Body_Log5_RoughEdge8", + "Body_Log5_RoughEdge9", + "Body_Log5_RoughEdge10", + "Body_Log5_RoughEdge11", + "Body_Log5_RoughEdge12", + "Body_Log5_Split0", + "Body_Log5_Split1", + "Body_Log5_Split2", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5741868019104004, + -0.525394082069397, + 0.0 + ], + "max": [ + 0.5741867423057556, + 0.525394082069397, + 1.4999998807907104 + ] + }, + "bounds_godot": { + "min": [ + -0.5741868019104004, + 0.0, + -0.525394082069397 + ], + "max": [ + 0.5741867423057556, + 1.4999998807907104, + 0.525394082069397 + ] + }, + "scale_applied": 0.9691392869232289, + "blender_version": "5.2.1 LTS", + "sha256": "c9411cc996b2aae77620c31dc1281dfdd972216c89a3c7b0acc98edc66f72fa4", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w05.json b/assets-source/phase4/records/w05.json new file mode 100644 index 0000000..d298f2e --- /dev/null +++ b/assets-source/phase4/records/w05.json @@ -0,0 +1,255 @@ +{ + "id": "w05", + "name": "Samenschleuder", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_w05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w05.blend", + "triangles": 50536, + "offline_sculpt_parts": 14, + "offline_render_triangles": 493876, + "mesh_parts": 204, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Launcher_Shell", + "Head_Launcher_Rim", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale4_Vein2_1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf1_Vein2_1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen" + ], + "bounds_blender": { + "min": [ + -0.4434923529624939, + -0.44349443912506104, + 0.0 + ], + "max": [ + 0.4434923529624939, + 0.44349443912506104, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.4434923529624939, + 0.0, + -0.44349443912506104 + ], + "max": [ + 0.4434923529624939, + 1.4499999284744263, + 0.44349443912506104 + ] + }, + "scale_applied": 0.9698799415431859, + "blender_version": "5.2.1 LTS", + "sha256": "7b5281fa0687e57df36a57639cd3a5325c16b5f7c7e094755cd1b53c14f2b873", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w06.json b/assets-source/phase4/records/w06.json new file mode 100644 index 0000000..fcb0983 --- /dev/null +++ b/assets-source/phase4/records/w06.json @@ -0,0 +1,347 @@ +{ + "id": "w06", + "name": "Zapfenkrone", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_w06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w06.blend", + "triangles": 62588, + "offline_sculpt_parts": 16, + "offline_render_triangles": 561488, + "mesh_parts": 296, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Launcher_Shell", + "Head_Launcher_Rim", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale5", + "Head_LauncherScale5_Midrib", + "Head_LauncherScale5_Vein0__1", + "Head_LauncherScale5_Vein0_1", + "Head_LauncherScale5_Vein1__1", + "Head_LauncherScale5_Vein1_1", + "Head_LauncherScale5_Vein2__1", + "Head_LauncherScale5_Vein2_1", + "Head_LauncherScale6", + "Head_LauncherScale6_Midrib", + "Head_LauncherScale6_Vein0__1", + "Head_LauncherScale6_Vein0_1", + "Head_LauncherScale6_Vein1__1", + "Head_LauncherScale6_Vein1_1", + "Head_LauncherScale6_Vein2__1", + "Head_LauncherScale6_Vein2_1", + "Head_LauncherScale7", + "Head_LauncherScale7_Midrib", + "Head_LauncherScale7_Vein0__1", + "Head_LauncherScale7_Vein0_1", + "Head_LauncherScale7_Vein1__1", + "Head_LauncherScale7_Vein1_1", + "Head_LauncherScale7_Vein2__1", + "Head_LauncherScale7_Vein2_1", + "Head_LauncherScale8", + "Head_LauncherScale8_Midrib", + "Head_LauncherScale8_Vein0__1", + "Head_LauncherScale8_Vein0_1", + "Head_LauncherScale8_Vein1__1", + "Head_LauncherScale8_Vein1_1", + "Head_LauncherScale8_Vein2__1", + "Head_LauncherScale8_Vein2_1", + "Head_LauncherScale9", + "Head_LauncherScale9_Midrib", + "Head_LauncherScale9_Vein0__1", + "Head_LauncherScale9_Vein0_1", + "Head_LauncherScale9_Vein1__1", + "Head_LauncherScale9_Vein1_1", + "Head_LauncherScale9_Vein2__1", + "Head_LauncherScale9_Vein2_1", + "Head_LauncherScale10", + "Head_LauncherScale10_Midrib", + "Head_LauncherScale10_Vein0__1", + "Head_LauncherScale10_Vein0_1", + "Head_LauncherScale10_Vein1__1", + "Head_LauncherScale10_Vein1_1", + "Head_LauncherScale10_Vein2__1", + "Head_LauncherScale10_Vein2_1", + "Head_LauncherScale11", + "Head_LauncherScale11_Midrib", + "Head_LauncherScale11_Vein0__1", + "Head_LauncherScale11_Vein0_1", + "Head_LauncherScale11_Vein1__1", + "Head_LauncherScale11_Vein1_1", + "Head_LauncherScale11_Vein2__1", + "Head_LauncherScale11_Vein2_1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf1_Vein2_1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen" + ], + "bounds_blender": { + "min": [ + -0.46449750661849976, + -0.46449971199035645, + 0.0 + ], + "max": [ + 0.46449750661849976, + 0.46449971199035645, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.46449750661849976, + 0.0, + -0.46449971199035645 + ], + "max": [ + 0.46449750661849976, + 1.600000023841858, + 0.46449971199035645 + ] + }, + "scale_applied": 1.0158164742306943, + "blender_version": "5.2.1 LTS", + "sha256": "103ec5d6c79dbb19bdc6cd8b00a1ed9811b6c0fc56d57eb8e386d32730754300", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w07.json b/assets-source/phase4/records/w07.json new file mode 100644 index 0000000..0470d69 --- /dev/null +++ b/assets-source/phase4/records/w07.json @@ -0,0 +1,417 @@ +{ + "id": "w07", + "name": "Sporenkelch", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w07.blend", + "triangles": 69164, + "offline_sculpt_parts": 9, + "offline_render_triangles": 534224, + "mesh_parts": 366, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Head_Cup0_Shell", + "Head_Cup0_Rim", + "Head_Cup0_Rib0", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Rib1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Rib2", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Rib3", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Rib4", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Rib5", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Rib6", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Rib7", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Rib8", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Rib9", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Rib10", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Rib11", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe11_Vein2_1", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Body_SmallCup0_Shell", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup1_Shell", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Fringe4_Vein2_1" + ], + "bounds_blender": { + "min": [ + -0.5578137040138245, + -0.5487784147262573, + 0.0 + ], + "max": [ + 0.5578137040138245, + 0.5487784147262573, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5578137040138245, + 0.0, + -0.5487784147262573 + ], + "max": [ + 0.5578137040138245, + 1.3499999046325684, + 0.5487784147262573 + ] + }, + "scale_applied": 1.0256522914156414, + "blender_version": "5.2.1 LTS", + "sha256": "16e4cb127fee12f5b3757d7bebc742b86b1dbd54c3512934ad21682f8c510ab1", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w08.json b/assets-source/phase4/records/w08.json new file mode 100644 index 0000000..e70e92d --- /dev/null +++ b/assets-source/phase4/records/w08.json @@ -0,0 +1,751 @@ +{ + "id": "w08", + "name": "Pilzkathedrale", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w08.blend", + "triangles": 103748, + "offline_sculpt_parts": 11, + "offline_render_triangles": 624368, + "mesh_parts": 700, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Head_Cup0_Shell", + "Head_Cup0_Rim", + "Head_Cup0_Rib0", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Rib1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Rib2", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Rib3", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Rib4", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Rib5", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Rib6", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Rib7", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Rib8", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Rib9", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Rib10", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Rib11", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe11_Vein2_1", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Body_FungalTrunk1", + "Body_FungalTrunk1_Grain0", + "Body_FungalTrunk1_Grain1", + "Body_FungalTrunk1_Grain2", + "Body_FungalTrunk1_Grain3", + "Head_Cup1_Shell", + "Head_Cup1_Rim", + "Head_Cup1_Rib0", + "Head_Cup1_Fringe0", + "Head_Cup1_Fringe0_Midrib", + "Head_Cup1_Fringe0_Vein0__1", + "Head_Cup1_Fringe0_Vein0_1", + "Head_Cup1_Fringe0_Vein1__1", + "Head_Cup1_Fringe0_Vein1_1", + "Head_Cup1_Fringe0_Vein2__1", + "Head_Cup1_Fringe0_Vein2_1", + "Head_Cup1_Rib1", + "Head_Cup1_Fringe1", + "Head_Cup1_Fringe1_Midrib", + "Head_Cup1_Fringe1_Vein0__1", + "Head_Cup1_Fringe1_Vein0_1", + "Head_Cup1_Fringe1_Vein1__1", + "Head_Cup1_Fringe1_Vein1_1", + "Head_Cup1_Fringe1_Vein2__1", + "Head_Cup1_Fringe1_Vein2_1", + "Head_Cup1_Rib2", + "Head_Cup1_Fringe2", + "Head_Cup1_Fringe2_Midrib", + "Head_Cup1_Fringe2_Vein0__1", + "Head_Cup1_Fringe2_Vein0_1", + "Head_Cup1_Fringe2_Vein1__1", + "Head_Cup1_Fringe2_Vein1_1", + "Head_Cup1_Fringe2_Vein2__1", + "Head_Cup1_Fringe2_Vein2_1", + "Head_Cup1_Rib3", + "Head_Cup1_Fringe3", + "Head_Cup1_Fringe3_Midrib", + "Head_Cup1_Fringe3_Vein0__1", + "Head_Cup1_Fringe3_Vein0_1", + "Head_Cup1_Fringe3_Vein1__1", + "Head_Cup1_Fringe3_Vein1_1", + "Head_Cup1_Fringe3_Vein2__1", + "Head_Cup1_Fringe3_Vein2_1", + "Head_Cup1_Rib4", + "Head_Cup1_Fringe4", + "Head_Cup1_Fringe4_Midrib", + "Head_Cup1_Fringe4_Vein0__1", + "Head_Cup1_Fringe4_Vein0_1", + "Head_Cup1_Fringe4_Vein1__1", + "Head_Cup1_Fringe4_Vein1_1", + "Head_Cup1_Fringe4_Vein2__1", + "Head_Cup1_Fringe4_Vein2_1", + "Head_Cup1_Rib5", + "Head_Cup1_Fringe5", + "Head_Cup1_Fringe5_Midrib", + "Head_Cup1_Fringe5_Vein0__1", + "Head_Cup1_Fringe5_Vein0_1", + "Head_Cup1_Fringe5_Vein1__1", + "Head_Cup1_Fringe5_Vein1_1", + "Head_Cup1_Fringe5_Vein2__1", + "Head_Cup1_Fringe5_Vein2_1", + "Head_Cup1_Rib6", + "Head_Cup1_Fringe6", + "Head_Cup1_Fringe6_Midrib", + "Head_Cup1_Fringe6_Vein0__1", + "Head_Cup1_Fringe6_Vein0_1", + "Head_Cup1_Fringe6_Vein1__1", + "Head_Cup1_Fringe6_Vein1_1", + "Head_Cup1_Fringe6_Vein2__1", + "Head_Cup1_Fringe6_Vein2_1", + "Head_Cup1_Rib7", + "Head_Cup1_Fringe7", + "Head_Cup1_Fringe7_Midrib", + "Head_Cup1_Fringe7_Vein0__1", + "Head_Cup1_Fringe7_Vein0_1", + "Head_Cup1_Fringe7_Vein1__1", + "Head_Cup1_Fringe7_Vein1_1", + "Head_Cup1_Fringe7_Vein2__1", + "Head_Cup1_Fringe7_Vein2_1", + "Head_Cup1_Rib8", + "Head_Cup1_Fringe8", + "Head_Cup1_Fringe8_Midrib", + "Head_Cup1_Fringe8_Vein0__1", + "Head_Cup1_Fringe8_Vein0_1", + "Head_Cup1_Fringe8_Vein1__1", + "Head_Cup1_Fringe8_Vein1_1", + "Head_Cup1_Fringe8_Vein2__1", + "Head_Cup1_Fringe8_Vein2_1", + "Head_Cup1_Rib9", + "Head_Cup1_Fringe9", + "Head_Cup1_Fringe9_Midrib", + "Head_Cup1_Fringe9_Vein0__1", + "Head_Cup1_Fringe9_Vein0_1", + "Head_Cup1_Fringe9_Vein1__1", + "Head_Cup1_Fringe9_Vein1_1", + "Head_Cup1_Fringe9_Vein2__1", + "Head_Cup1_Fringe9_Vein2_1", + "Head_Cup1_Rib10", + "Head_Cup1_Fringe10", + "Head_Cup1_Fringe10_Midrib", + "Head_Cup1_Fringe10_Vein0__1", + "Head_Cup1_Fringe10_Vein0_1", + "Head_Cup1_Fringe10_Vein1__1", + "Head_Cup1_Fringe10_Vein1_1", + "Head_Cup1_Fringe10_Vein2__1", + "Head_Cup1_Fringe10_Vein2_1", + "Head_Cup1_Rib11", + "Head_Cup1_Fringe11", + "Head_Cup1_Fringe11_Midrib", + "Head_Cup1_Fringe11_Vein0__1", + "Head_Cup1_Fringe11_Vein0_1", + "Head_Cup1_Fringe11_Vein1__1", + "Head_Cup1_Fringe11_Vein1_1", + "Head_Cup1_Fringe11_Vein2__1", + "Head_Cup1_Fringe11_Vein2_1", + "Weapon_Spore1_0", + "Weapon_Spore1_1", + "Weapon_Spore1_2", + "Weapon_Spore1_3", + "Weapon_Spore1_4", + "Body_FungalTrunk2", + "Body_FungalTrunk2_Grain0", + "Body_FungalTrunk2_Grain1", + "Body_FungalTrunk2_Grain2", + "Body_FungalTrunk2_Grain3", + "Head_Cup2_Shell", + "Head_Cup2_Rim", + "Head_Cup2_Rib0", + "Head_Cup2_Fringe0", + "Head_Cup2_Fringe0_Midrib", + "Head_Cup2_Fringe0_Vein0__1", + "Head_Cup2_Fringe0_Vein0_1", + "Head_Cup2_Fringe0_Vein1__1", + "Head_Cup2_Fringe0_Vein1_1", + "Head_Cup2_Fringe0_Vein2__1", + "Head_Cup2_Fringe0_Vein2_1", + "Head_Cup2_Rib1", + "Head_Cup2_Fringe1", + "Head_Cup2_Fringe1_Midrib", + "Head_Cup2_Fringe1_Vein0__1", + "Head_Cup2_Fringe1_Vein0_1", + "Head_Cup2_Fringe1_Vein1__1", + "Head_Cup2_Fringe1_Vein1_1", + "Head_Cup2_Fringe1_Vein2__1", + "Head_Cup2_Fringe1_Vein2_1", + "Head_Cup2_Rib2", + "Head_Cup2_Fringe2", + "Head_Cup2_Fringe2_Midrib", + "Head_Cup2_Fringe2_Vein0__1", + "Head_Cup2_Fringe2_Vein0_1", + "Head_Cup2_Fringe2_Vein1__1", + "Head_Cup2_Fringe2_Vein1_1", + "Head_Cup2_Fringe2_Vein2__1", + "Head_Cup2_Fringe2_Vein2_1", + "Head_Cup2_Rib3", + "Head_Cup2_Fringe3", + "Head_Cup2_Fringe3_Midrib", + "Head_Cup2_Fringe3_Vein0__1", + "Head_Cup2_Fringe3_Vein0_1", + "Head_Cup2_Fringe3_Vein1__1", + "Head_Cup2_Fringe3_Vein1_1", + "Head_Cup2_Fringe3_Vein2__1", + "Head_Cup2_Fringe3_Vein2_1", + "Head_Cup2_Rib4", + "Head_Cup2_Fringe4", + "Head_Cup2_Fringe4_Midrib", + "Head_Cup2_Fringe4_Vein0__1", + "Head_Cup2_Fringe4_Vein0_1", + "Head_Cup2_Fringe4_Vein1__1", + "Head_Cup2_Fringe4_Vein1_1", + "Head_Cup2_Fringe4_Vein2__1", + "Head_Cup2_Fringe4_Vein2_1", + "Head_Cup2_Rib5", + "Head_Cup2_Fringe5", + "Head_Cup2_Fringe5_Midrib", + "Head_Cup2_Fringe5_Vein0__1", + "Head_Cup2_Fringe5_Vein0_1", + "Head_Cup2_Fringe5_Vein1__1", + "Head_Cup2_Fringe5_Vein1_1", + "Head_Cup2_Fringe5_Vein2__1", + "Head_Cup2_Fringe5_Vein2_1", + "Head_Cup2_Rib6", + "Head_Cup2_Fringe6", + "Head_Cup2_Fringe6_Midrib", + "Head_Cup2_Fringe6_Vein0__1", + "Head_Cup2_Fringe6_Vein0_1", + "Head_Cup2_Fringe6_Vein1__1", + "Head_Cup2_Fringe6_Vein1_1", + "Head_Cup2_Fringe6_Vein2__1", + "Head_Cup2_Fringe6_Vein2_1", + "Head_Cup2_Rib7", + "Head_Cup2_Fringe7", + "Head_Cup2_Fringe7_Midrib", + "Head_Cup2_Fringe7_Vein0__1", + "Head_Cup2_Fringe7_Vein0_1", + "Head_Cup2_Fringe7_Vein1__1", + "Head_Cup2_Fringe7_Vein1_1", + "Head_Cup2_Fringe7_Vein2__1", + "Head_Cup2_Fringe7_Vein2_1", + "Head_Cup2_Rib8", + "Head_Cup2_Fringe8", + "Head_Cup2_Fringe8_Midrib", + "Head_Cup2_Fringe8_Vein0__1", + "Head_Cup2_Fringe8_Vein0_1", + "Head_Cup2_Fringe8_Vein1__1", + "Head_Cup2_Fringe8_Vein1_1", + "Head_Cup2_Fringe8_Vein2__1", + "Head_Cup2_Fringe8_Vein2_1", + "Head_Cup2_Rib9", + "Head_Cup2_Fringe9", + "Head_Cup2_Fringe9_Midrib", + "Head_Cup2_Fringe9_Vein0__1", + "Head_Cup2_Fringe9_Vein0_1", + "Head_Cup2_Fringe9_Vein1__1", + "Head_Cup2_Fringe9_Vein1_1", + "Head_Cup2_Fringe9_Vein2__1", + "Head_Cup2_Fringe9_Vein2_1", + "Head_Cup2_Rib10", + "Head_Cup2_Fringe10", + "Head_Cup2_Fringe10_Midrib", + "Head_Cup2_Fringe10_Vein0__1", + "Head_Cup2_Fringe10_Vein0_1", + "Head_Cup2_Fringe10_Vein1__1", + "Head_Cup2_Fringe10_Vein1_1", + "Head_Cup2_Fringe10_Vein2__1", + "Head_Cup2_Fringe10_Vein2_1", + "Head_Cup2_Rib11", + "Head_Cup2_Fringe11", + "Head_Cup2_Fringe11_Midrib", + "Head_Cup2_Fringe11_Vein0__1", + "Head_Cup2_Fringe11_Vein0_1", + "Head_Cup2_Fringe11_Vein1__1", + "Head_Cup2_Fringe11_Vein1_1", + "Head_Cup2_Fringe11_Vein2__1", + "Head_Cup2_Fringe11_Vein2_1", + "Weapon_Spore2_0", + "Weapon_Spore2_1", + "Weapon_Spore2_2", + "Weapon_Spore2_3", + "Weapon_Spore2_4", + "Body_SmallCup0_Shell", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup1_Shell", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup2_Shell", + "Body_SmallCup2_Rim", + "Body_SmallCup2_Rib0", + "Body_SmallCup2_Fringe0", + "Body_SmallCup2_Fringe0_Midrib", + "Body_SmallCup2_Fringe0_Vein0__1", + "Body_SmallCup2_Fringe0_Vein0_1", + "Body_SmallCup2_Fringe0_Vein1__1", + "Body_SmallCup2_Fringe0_Vein1_1", + "Body_SmallCup2_Fringe0_Vein2__1", + "Body_SmallCup2_Fringe0_Vein2_1", + "Body_SmallCup2_Rib1", + "Body_SmallCup2_Fringe1", + "Body_SmallCup2_Fringe1_Midrib", + "Body_SmallCup2_Fringe1_Vein0__1", + "Body_SmallCup2_Fringe1_Vein0_1", + "Body_SmallCup2_Fringe1_Vein1__1", + "Body_SmallCup2_Fringe1_Vein1_1", + "Body_SmallCup2_Fringe1_Vein2__1", + "Body_SmallCup2_Fringe1_Vein2_1", + "Body_SmallCup2_Rib2", + "Body_SmallCup2_Fringe2", + "Body_SmallCup2_Fringe2_Midrib", + "Body_SmallCup2_Fringe2_Vein0__1", + "Body_SmallCup2_Fringe2_Vein0_1", + "Body_SmallCup2_Fringe2_Vein1__1", + "Body_SmallCup2_Fringe2_Vein1_1", + "Body_SmallCup2_Fringe2_Vein2__1", + "Body_SmallCup2_Fringe2_Vein2_1", + "Body_SmallCup2_Rib3", + "Body_SmallCup2_Fringe3", + "Body_SmallCup2_Fringe3_Midrib", + "Body_SmallCup2_Fringe3_Vein0__1", + "Body_SmallCup2_Fringe3_Vein0_1", + "Body_SmallCup2_Fringe3_Vein1__1", + "Body_SmallCup2_Fringe3_Vein1_1", + "Body_SmallCup2_Fringe3_Vein2__1", + "Body_SmallCup2_Fringe3_Vein2_1", + "Body_SmallCup2_Rib4", + "Body_SmallCup2_Fringe4", + "Body_SmallCup2_Fringe4_Midrib", + "Body_SmallCup2_Fringe4_Vein0__1", + "Body_SmallCup2_Fringe4_Vein0_1", + "Body_SmallCup2_Fringe4_Vein1__1", + "Body_SmallCup2_Fringe4_Vein1_1", + "Body_SmallCup2_Fringe4_Vein2__1", + "Body_SmallCup2_Fringe4_Vein2_1", + "Body_SmallCup3_Shell", + "Body_SmallCup3_Rim", + "Body_SmallCup3_Rib0", + "Body_SmallCup3_Fringe0", + "Body_SmallCup3_Fringe0_Midrib", + "Body_SmallCup3_Fringe0_Vein0__1", + "Body_SmallCup3_Fringe0_Vein0_1", + "Body_SmallCup3_Fringe0_Vein1__1", + "Body_SmallCup3_Fringe0_Vein1_1", + "Body_SmallCup3_Fringe0_Vein2__1", + "Body_SmallCup3_Fringe0_Vein2_1", + "Body_SmallCup3_Rib1", + "Body_SmallCup3_Fringe1", + "Body_SmallCup3_Fringe1_Midrib", + "Body_SmallCup3_Fringe1_Vein0__1", + "Body_SmallCup3_Fringe1_Vein0_1", + "Body_SmallCup3_Fringe1_Vein1__1", + "Body_SmallCup3_Fringe1_Vein1_1", + "Body_SmallCup3_Fringe1_Vein2__1", + "Body_SmallCup3_Fringe1_Vein2_1", + "Body_SmallCup3_Rib2", + "Body_SmallCup3_Fringe2", + "Body_SmallCup3_Fringe2_Midrib", + "Body_SmallCup3_Fringe2_Vein0__1", + "Body_SmallCup3_Fringe2_Vein0_1", + "Body_SmallCup3_Fringe2_Vein1__1", + "Body_SmallCup3_Fringe2_Vein1_1", + "Body_SmallCup3_Fringe2_Vein2__1", + "Body_SmallCup3_Fringe2_Vein2_1", + "Body_SmallCup3_Rib3", + "Body_SmallCup3_Fringe3", + "Body_SmallCup3_Fringe3_Midrib", + "Body_SmallCup3_Fringe3_Vein0__1", + "Body_SmallCup3_Fringe3_Vein0_1", + "Body_SmallCup3_Fringe3_Vein1__1", + "Body_SmallCup3_Fringe3_Vein1_1", + "Body_SmallCup3_Fringe3_Vein2__1", + "Body_SmallCup3_Fringe3_Vein2_1", + "Body_SmallCup3_Rib4", + "Body_SmallCup3_Fringe4", + "Body_SmallCup3_Fringe4_Midrib", + "Body_SmallCup3_Fringe4_Vein0__1", + "Body_SmallCup3_Fringe4_Vein0_1", + "Body_SmallCup3_Fringe4_Vein1__1", + "Body_SmallCup3_Fringe4_Vein1_1", + "Body_SmallCup3_Fringe4_Vein2__1", + "Body_SmallCup3_Fringe4_Vein2_1" + ], + "bounds_blender": { + "min": [ + -0.594677209854126, + -0.5008414387702942, + 0.0 + ], + "max": [ + 0.5946771502494812, + 0.5008414387702942, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.594677209854126, + 0.0, + -0.5008414387702942 + ], + "max": [ + 0.5946771502494812, + 1.5, + 0.5008414387702942 + ] + }, + "scale_applied": 0.9111697095323008, + "blender_version": "5.2.1 LTS", + "sha256": "f20be99b5ae730c6dbd37ca3c635b8953f3d5d852093586ba1790022edea1a75", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w09.json b/assets-source/phase4/records/w09.json new file mode 100644 index 0000000..bb7d34a --- /dev/null +++ b/assets-source/phase4/records/w09.json @@ -0,0 +1,250 @@ +{ + "id": "w09", + "name": "Tauhüter", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_w09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w09.blend", + "triangles": 52040, + "offline_sculpt_parts": 8, + "offline_render_triangles": 489320, + "mesh_parts": 199, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Crown0", + "Head_Crown0_Midrib", + "Head_Crown0_Vein0__1", + "Head_Crown0_Vein0_1", + "Head_Crown0_Vein1__1", + "Head_Crown0_Vein1_1", + "Head_Crown0_Vein2__1", + "Head_Crown0_Vein2_1", + "Head_Crown1", + "Head_Crown1_Midrib", + "Head_Crown1_Vein0__1", + "Head_Crown1_Vein0_1", + "Head_Crown1_Vein1__1", + "Head_Crown1_Vein1_1", + "Head_Crown1_Vein2__1", + "Head_Crown1_Vein2_1", + "Head_Crown2", + "Head_Crown2_Midrib", + "Head_Crown2_Vein0__1", + "Head_Crown2_Vein0_1", + "Head_Crown2_Vein1__1", + "Head_Crown2_Vein1_1", + "Head_Crown2_Vein2__1", + "Head_Crown2_Vein2_1", + "Head_Crown3", + "Head_Crown3_Midrib", + "Head_Crown3_Vein0__1", + "Head_Crown3_Vein0_1", + "Head_Crown3_Vein1__1", + "Head_Crown3_Vein1_1", + "Head_Crown3_Vein2__1", + "Head_Crown3_Vein2_1", + "Head_Crown4", + "Head_Crown4_Midrib", + "Head_Crown4_Vein0__1", + "Head_Crown4_Vein0_1", + "Head_Crown4_Vein1__1", + "Head_Crown4_Vein1_1", + "Head_Crown4_Vein2__1", + "Head_Crown4_Vein2_1", + "Weapon_Basin_Shell", + "Weapon_Basin_Rim", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Water", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_DewOrb", + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen" + ], + "bounds_blender": { + "min": [ + -0.4580939710140228, + -0.4580966830253601, + 0.0 + ], + "max": [ + 0.4580939710140228, + 0.4580966830253601, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.4580939710140228, + 0.0, + -0.4580966830253601 + ], + "max": [ + 0.4580939710140228, + 1.4500000476837158, + 0.4580966830253601 + ] + }, + "scale_applied": 0.9039585320704921, + "blender_version": "5.2.1 LTS", + "sha256": "55b1acf214f81151158e1fd7caac2fe9362fcd3fcf67b16c1d7fffebe11b10f1", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/w10.json b/assets-source/phase4/records/w10.json new file mode 100644 index 0000000..f284c24 --- /dev/null +++ b/assets-source/phase4/records/w10.json @@ -0,0 +1,399 @@ +{ + "id": "w10", + "name": "Quellgeflecht", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_w10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w10.blend", + "triangles": 61052, + "offline_sculpt_parts": 12, + "offline_render_triangles": 475052, + "mesh_parts": 348, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Arch_1_0", + "Body_Arch_1_0_Grain0", + "Body_Arch_1_0_Grain1", + "Body_Arch_1_0_Grain2", + "Body_Arch_1_1", + "Body_Arch_1_1_Grain0", + "Body_Arch_1_1_Grain1", + "Body_Arch_1_1_Grain2", + "Body_Arch_1_2", + "Body_Arch_1_2_Grain0", + "Body_Arch_1_2_Grain1", + "Body_Arch_1_2_Grain2", + "Body_Arch1_0", + "Body_Arch1_0_Grain0", + "Body_Arch1_0_Grain1", + "Body_Arch1_0_Grain2", + "Body_Arch1_1", + "Body_Arch1_1_Grain0", + "Body_Arch1_1_Grain1", + "Body_Arch1_1_Grain2", + "Body_Arch1_2", + "Body_Arch1_2_Grain0", + "Body_Arch1_2_Grain1", + "Body_Arch1_2_Grain2", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy11", + "Head_Canopy11_Midrib", + "Head_Canopy11_Vein0__1", + "Head_Canopy11_Vein0_1", + "Head_Canopy11_Vein1__1", + "Head_Canopy11_Vein1_1", + "Head_Canopy11_Vein2__1", + "Head_Canopy11_Vein2_1", + "Head_Canopy12", + "Head_Canopy12_Midrib", + "Head_Canopy12_Vein0__1", + "Head_Canopy12_Vein0_1", + "Head_Canopy12_Vein1__1", + "Head_Canopy12_Vein1_1", + "Head_Canopy12_Vein2__1", + "Head_Canopy12_Vein2_1", + "Head_Canopy13", + "Head_Canopy13_Midrib", + "Head_Canopy13_Vein0__1", + "Head_Canopy13_Vein0_1", + "Head_Canopy13_Vein1__1", + "Head_Canopy13_Vein1_1", + "Head_Canopy13_Vein2__1", + "Head_Canopy13_Vein2_1", + "Head_Canopy14", + "Head_Canopy14_Midrib", + "Head_Canopy14_Vein0__1", + "Head_Canopy14_Vein0_1", + "Head_Canopy14_Vein1__1", + "Head_Canopy14_Vein1_1", + "Head_Canopy14_Vein2__1", + "Head_Canopy14_Vein2_1", + "Head_Canopy15", + "Head_Canopy15_Midrib", + "Head_Canopy15_Vein0__1", + "Head_Canopy15_Vein0_1", + "Head_Canopy15_Vein1__1", + "Head_Canopy15_Vein1_1", + "Head_Canopy15_Vein2__1", + "Head_Canopy15_Vein2_1", + "Head_Canopy16", + "Head_Canopy16_Midrib", + "Head_Canopy16_Vein0__1", + "Head_Canopy16_Vein0_1", + "Head_Canopy16_Vein1__1", + "Head_Canopy16_Vein1_1", + "Head_Canopy16_Vein2__1", + "Head_Canopy16_Vein2_1", + "Head_Canopy17", + "Head_Canopy17_Midrib", + "Head_Canopy17_Vein0__1", + "Head_Canopy17_Vein0_1", + "Head_Canopy17_Vein1__1", + "Head_Canopy17_Vein1_1", + "Head_Canopy17_Vein2__1", + "Head_Canopy17_Vein2_1", + "Head_Canopy18", + "Head_Canopy18_Midrib", + "Head_Canopy18_Vein0__1", + "Head_Canopy18_Vein0_1", + "Head_Canopy18_Vein1__1", + "Head_Canopy18_Vein1_1", + "Head_Canopy18_Vein2__1", + "Head_Canopy18_Vein2_1", + "Head_Canopy19", + "Head_Canopy19_Midrib", + "Head_Canopy19_Vein0__1", + "Head_Canopy19_Vein0_1", + "Head_Canopy19_Vein1__1", + "Head_Canopy19_Vein1_1", + "Head_Canopy19_Vein2__1", + "Head_Canopy19_Vein2_1", + "Head_Canopy20", + "Head_Canopy20_Midrib", + "Head_Canopy20_Vein0__1", + "Head_Canopy20_Vein0_1", + "Head_Canopy20_Vein1__1", + "Head_Canopy20_Vein1_1", + "Head_Canopy20_Vein2__1", + "Head_Canopy20_Vein2_1", + "Head_Canopy21", + "Head_Canopy21_Midrib", + "Head_Canopy21_Vein0__1", + "Head_Canopy21_Vein0_1", + "Head_Canopy21_Vein1__1", + "Head_Canopy21_Vein1_1", + "Head_Canopy21_Vein2__1", + "Head_Canopy21_Vein2_1", + "Head_Canopy22", + "Head_Canopy22_Midrib", + "Head_Canopy22_Vein0__1", + "Head_Canopy22_Vein0_1", + "Head_Canopy22_Vein1__1", + "Head_Canopy22_Vein1_1", + "Head_Canopy22_Vein2__1", + "Head_Canopy22_Vein2_1", + "Head_Canopy23", + "Head_Canopy23_Midrib", + "Head_Canopy23_Vein0__1", + "Head_Canopy23_Vein0_1", + "Head_Canopy23_Vein1__1", + "Head_Canopy23_Vein1_1", + "Head_Canopy23_Vein2__1", + "Head_Canopy23_Vein2_1", + "Weapon_Basin_Shell", + "Weapon_Basin_Rim", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Water", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_Blossom3_Pollen", + "Body_Blossom4_Petal0", + "Body_Blossom4_Petal1", + "Body_Blossom4_Petal2", + "Body_Blossom4_Petal3", + "Body_Blossom4_Petal4", + "Body_Blossom4_Pollen", + "Body_Blossom5_Petal0", + "Body_Blossom5_Petal1", + "Body_Blossom5_Petal2", + "Body_Blossom5_Petal3", + "Body_Blossom5_Petal4", + "Body_Blossom5_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5408053994178772, + -0.5766830444335938, + 0.0 + ], + "max": [ + 0.5408053994178772, + 0.5766830444335938, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.5408053994178772, + 0.0, + -0.5766830444335938 + ], + "max": [ + 0.5408053994178772, + 1.600000023841858, + 0.5766830444335938 + ] + }, + "scale_applied": 1.0671733294701777, + "blender_version": "5.2.1 LTS", + "sha256": "c17b2d1aa6dc2eb4a627a8509362c24c1224e942ac72ab40db3d25e1f78ca340", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" +} diff --git a/assets-source/phase4/records/worker.json b/assets-source/phase4/records/worker.json new file mode 100644 index 0000000..3ce1624 --- /dev/null +++ b/assets-source/phase4/records/worker.json @@ -0,0 +1,116 @@ +{ + "id": "worker", + "name": "Funkenleser", + "faction": "neutral", + "palette": "worker", + "role": "worker", + "upgraded": false, + "height": 1.1, + "footprint": 1.4, + "file": "worker.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/worker.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/worker.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/worker.blend", + "triangles": 24026, + "mesh_parts": 65, + "parts": [ + "LegL_Shin", + "LegL_Boot", + "LegL_Sole", + "LegL_Cuff", + "LegL_ToeRidge0", + "LegL_ToeRidge1", + "LegL_ToeRidge2", + "LegR_Shin", + "LegR_Boot", + "LegR_Sole", + "LegR_Cuff", + "LegR_ToeRidge0", + "LegR_ToeRidge1", + "LegR_ToeRidge2", + "Body_ClayTorso", + "Body_LeatherApron", + "Body_ApronRivet0", + "Body_ApronRivet1", + "Body_ApronRivet2", + "Body_ApronRivet3", + "Body_ApronRivet4", + "Body_ApronRivet5", + "Body_ApronRivet6", + "Body_ToolPocket", + "Body_Harness_1", + "Body_Harness1", + "Head_Hood", + "Head_FaceRecess", + "Head_GoggleSocket_1", + "Head_GoggleLens_1", + "Head_GoggleGlint_1", + "Head_GoggleSocket1", + "Head_GoggleLens1", + "Head_GoggleGlint1", + "Head_Cap", + "Head_LampHousing", + "Head_Lamp", + "Body_Reservoir", + "Body_TankRim0_45", + "Body_TankRim0_79", + "Body_TankBrace0", + "Body_TankBrace1", + "Body_TankBrace2", + "Body_TankBrace3", + "Body_TankBrace4", + "Body_TankBrace5", + "Body_TankBrace6", + "Body_TankBrace7", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Glove", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Glove", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "WeaponL_Handle", + "WeaponL_Fork", + "WeaponR_Probe" + ], + "bounds_blender": { + "min": [ + -0.4626109004020691, + -0.4145205020904541, + 0.0 + ], + "max": [ + 0.4626109302043915, + 0.4145205020904541, + 1.100000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.4626109004020691, + 0.0, + -0.4145205020904541 + ], + "max": [ + 0.4626109302043915, + 1.100000023841858, + 0.4145205020904541 + ] + }, + "scale_applied": 1.0471664901050803, + "blender_version": "5.2.1 LTS", + "sha256": "c783cbaf9635bb97576d574f514a1ede4b4d52250b24c0e68f1052281ead017a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 6, + "offline_render_triangles": 103466 +} diff --git a/assets-source/phase4/revisions/before-icon-match.tar.gz b/assets-source/phase4/revisions/before-icon-match.tar.gz new file mode 100644 index 0000000..29510b4 Binary files /dev/null and b/assets-source/phase4/revisions/before-icon-match.tar.gz differ diff --git a/assets-source/phase4/standalone/__pycache__/create_artillery.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_artillery.cpython-314.pyc new file mode 100644 index 0000000..47447cd Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_artillery.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_core.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_core.cpython-314.pyc new file mode 100644 index 0000000..8b322ee Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_core.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_lane.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_lane.cpython-314.pyc new file mode 100644 index 0000000..3eec1bc Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_lane.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_melee.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_melee.cpython-314.pyc new file mode 100644 index 0000000..753d771 Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_melee.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_mercenary.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_mercenary.cpython-314.pyc new file mode 100644 index 0000000..3d56799 Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_mercenary.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_ranged.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_ranged.cpython-314.pyc new file mode 100644 index 0000000..5af9afb Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_ranged.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_support.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_support.cpython-314.pyc new file mode 100644 index 0000000..6fe0ef6 Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_support.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_tank.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_tank.cpython-314.pyc new file mode 100644 index 0000000..c213168 Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_tank.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/__pycache__/create_worker.cpython-314.pyc b/assets-source/phase4/standalone/__pycache__/create_worker.cpython-314.pyc new file mode 100644 index 0000000..4cb0903 Binary files /dev/null and b/assets-source/phase4/standalone/__pycache__/create_worker.cpython-314.pyc differ diff --git a/assets-source/phase4/standalone/create_artillery.py b/assets-source/phase4/standalone/create_artillery.py new file mode 100644 index 0000000..1b7c3fe --- /dev/null +++ b/assets-source/phase4/standalone/create_artillery.py @@ -0,0 +1,3440 @@ +"""Saumwacht · Flächenkämpfer · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'g07' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'g07', + 'name': 'Aschenwerfer', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'artillery', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_g07.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'g08', + 'name': 'Kraterrufer', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'artillery', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_g08.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'm07', + 'name': 'Klangkolben', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'artillery', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_m07.glb'}, + {'id': 'm08', + 'name': 'Resonanzramme', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'artillery', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_m08.glb'}, + {'id': 'n07', + 'name': 'Glockenschlepper', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'artillery', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_n07.glb'}, + {'id': 'n08', + 'name': 'Hohlgeläut', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'artillery', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_n08.glb'}, + {'id': 'w07', + 'name': 'Sporenkelch', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'artillery', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_w07.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'w08', + 'name': 'Pilzkathedrale', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'artillery', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_w08.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, sin, pi, sqrt + + + +def _add(a, b): + return tuple(a[i] + b[i] for i in range(3)) + + +def _mul(a, scale): + return tuple(v * scale for v in a) + + +def _cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def _unit(a): + length = sqrt(sum(v * v for v in a)) + return tuple(v / length for v in a) + + +def _frame(axis): + w = _unit(axis) + reference = (0, 0, 1) if abs(w[2]) < .9 else (0, 1, 0) + u = _unit(_cross(reference, w)) + return u, _cross(w, u), w + + +def _lathe(name, loc, profile, mat, axis=(0, 0, 1), segments=10): + """Closed profile, including real inner walls; zero radii become poles. + + Profile travels from the back/bottom up the outside, down the inside. + Independent pole vertices avoid degenerate zero-area triangles. + """ + u, v, w = _frame(axis) + verts, loops, faces = [], [], [] + for radius, depth in profile: + if radius == 0: + loops.append([len(verts)]) + verts.append(_add(loc, _mul(w, depth))) + continue + loop = [] + for k in range(segments): + angle = 2 * pi * k / segments + offset = _add(_mul(w, depth), + _add(_mul(u, radius * cos(angle)), + _mul(v, radius * sin(angle)))) + loop.append(len(verts)) + verts.append(_add(loc, offset)) + loops.append(loop) + for j in range(len(loops)): + low, high = loops[j], loops[(j + 1) % len(loops)] + if len(low) == 1 and len(high) == 1: + continue + for k in range(segments): + nxt = (k + 1) % segments + if len(low) == 1: + faces.append((low[0], high[nxt], high[k])) + elif len(high) == 1: + faces.append((low[k], low[nxt], high[0])) + else: + faces.append((low[k], low[nxt], high[nxt], high[k])) + mesh_object(name, verts, faces, mat) + + +def _cup(name, loc, radius, depth, mat, axis=(0, 0, 1), segments=10): + # The rim is 13% thick; the inset bottom is visible from above/front. + _lathe(name, loc, [(0, 0), (radius * .5, .04), + (radius * .73, depth * .35), (radius, depth), + (radius * .87, depth), (radius * .59, depth * .35), + (0, depth * .20)], mat, axis, segments) + + +def _horn(name, loc, radius, depth, mat, axis=(0, -1, .18)): + _lathe(name, loc, [(radius * .16, 0), (radius * .25, depth * .42), + (radius * .58, depth * .76), (radius, depth), + (radius * .84, depth), (radius * .43, depth * .72), + (radius * .1, depth * .35), (0, depth * .29), + (0, 0)], mat, axis, 10) + + +def _spike(name, start, end, radius, mat, sides=5): + axis = tuple(end[i] - start[i] for i in range(3)) + u, v, _ = _frame(axis) + verts = [_add(start, _add(_mul(u, radius * cos(2 * pi * k / sides)), + _mul(v, radius * sin(2 * pi * k / sides)))) + for k in range(sides)] + verts.append(end) + faces = [tuple(reversed(range(sides)))] + faces.extend((k, (k + 1) % sides, sides) for k in range(sides)) + mesh_object(name, verts, faces, mat) + + +def _leaf(name, loc, width, height, mat, lean=0): + # Thick diamond leaf: large central ridge, only eight triangles. + x, y, z = loc + verts = [(x, y, z), (x - width / 2, y, z + height * .42), + (x + lean, y + .05, z + height), + (x + width / 2, y, z + height * .42), + (x + lean * .3, y - .09, z + height * .45), + (x + lean * .3, y + .055, z + height * .45)] + faces = [(0, 4, 1), (1, 4, 2), (2, 4, 3), (3, 4, 0), + (1, 5, 0), (2, 5, 1), (3, 5, 2), (0, 5, 3)] + mesh_object(name, verts, faces, mat) + + +def _eyes(loc, mat, spread=.075, scale=.038): + for side, suffix in ((-1, "L"), (1, "R")): + p = (loc[0] + side * spread, loc[1], loc[2]) + ellipsoid("Head_Eye" + suffix, p, (scale, .023, scale * .75), mat) + + +def _mask(name, loc, scale, mat, eyes_mat): + ellipsoid(name, loc, (.15 * scale, .075 * scale, .22 * scale), mat) + for sign, suffix in ((-1, "L"), (1, "R")): + ellipsoid(name + "_Eye" + suffix, + (loc[0] + sign * .052 * scale, loc[1] - .071 * scale, + loc[2] + .023 * scale), + (.028 * scale, .012 * scale, .046 * scale), eyes_mat) + + +def _basalt_legs(mat, wide=False): + spread = .32 if wide else .22 + for side, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Leg" + suffix + "_Foot", (side * spread, -.075, .12), + (.20 if wide else .15, .24, .12), mat) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .15), + (side * spread * .7, .02, .49), .095, mat, vertices=6) + + +def _mechanical_legs(mat, wide=False): + spread = .27 if wide else .20 + for side, suffix in ((-1, "L"), (1, "R")): + box("Leg" + suffix + "_Foot", (side * spread, -.07, .07), + (.22, .33, .14), mat["accent"]) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .14), + (side * spread, .08, .35), .065, mat["accent"], vertices=6) + ellipsoid("Leg" + suffix + "_Knee", (side * spread, .08, .35), + (.10, .10, .10), mat["secondary"]) + beam("Leg" + suffix + "_Thigh", (side * spread, .08, .35), + (side * spread * .66, 0, .57), .09, mat["primary"], vertices=6) + + +def _root_feet(mat, count=4, spread=.43, top=.60): + for k in range(count): + a = 2 * pi * k / count + pi / 4 + base = (spread * cos(a), spread * sin(a), .055) + elbow = (spread * .6 * cos(a), spread * .6 * sin(a), .24) + suffix = str(k + 1) + beam("Leg_Root" + suffix, base, elbow, .09, mat, vertices=5) + beam("Leg_RootUpper" + suffix, elbow, (0, .02, top), .12, + mat, vertices=5) + ellipsoid("Leg_RootToe" + suffix, base, (.16, .10, .055), mat) + + +def _mist_robe(mat, upgraded=False): + # Alternating long cloth points touch the floor; the upper body floats. + cone("Body_Robe", (0, .035, .49), .31 if upgraded else .25, + .13, .74, mat["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + _spike("Body_ClothPoint" + str(k), + (.16 * cos(a), .035 + .16 * sin(a), .35), + (.31 * cos(a), .035 + .27 * sin(a), .015), .11, + mat["secondary"] if k % 2 else mat["primary"]) + ellipsoid("Body_Chest", (0, 0, .90), (.23, .16, .23), mat["secondary"]) + + +def _glut_ranged(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_Core", (0, .035, .69), (.30 if up else .21, .22, .27), + m["primary"]) + ellipsoid("Head_Helm", (0, -.015, 1.12), (.19, .16, .20), m["light"]) + _eyes((0, -.17, 1.13), m["secondary"]) + box("Body_Ember", (0, -.197, .71), (.11, .045, .19), m["secondary"]) + if up: + # Broad glass bow arms distinguish the upgrade from the slender lance. + box("Weapon_Rail", (0, -.20, .96), (.10, .98, .09), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .2, 0, .88), (s * .30, -.15, .91), + .075, m["primary"], vertices=6) + _spike("Weapon_GlassBow" + suffix, (s * .06, -.25, .99), + (s * .62, -.04, 1.25), .16, m["secondary"]) + beam("Weapon_String" + suffix, (s * .62, -.04, 1.25), + (0, .22, 1.03), .012, m["light"], vertices=4) + beam("Weapon_Bolt", (0, .20, 1.02), (0, -.64, 1.02), .025, m["light"]) + _spike("Weapon_BoltHead", (0, -.57, 1.02), (0, -.80, 1.02), + .08, m["secondary"]) + else: + beam("ArmL", (-.15, 0, .89), (-.25, -.07, .70), .07, m["primary"]) + beam("ArmR", (.15, 0, .90), (.30, -.19, .91), .075, m["primary"]) + beam("Weapon_Lance", (.29, .34, .81), (.29, -.60, 1.05), .038, + m["accent"]) + _spike("Weapon_GlassTip", (.29, -.53, 1.03), (.29, -.81, 1.11), + .105, m["secondary"]) + + +def _nieten_ranged(up, m): + _mechanical_legs(m) + cone("Body_Cuirass", (0, .02, .78), .21, .27, .43, m["primary"], vertices=6) + box("Body_Plate", (0, -.18, .80), (.27, .09, .22), m["secondary"]) + beam("Head_Neck", (0, 0, 1.0), (0, 0, 1.10), .075, m["accent"]) + box("Head_Housing", (0, -.015, 1.22), (.29, .25, .25), m["light"]) + box("Head_Visor", (0, -.146, 1.23), (.18, .028, .05), m["primary"]) + weapon_x = 0 if up else .29 + beam("ArmL", (-.21, 0, .92), (-.28, -.13, .77), .065, m["accent"]) + beam("ArmR", (.21, 0, .92), (weapon_x + .07, -.24, .91), .065, + m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Weapon_Rail" + suffix, (weapon_x + s * .055, -.30, .97), + (.055, .82 if up else .61, .07), m["accent"]) + tip = (weapon_x + s * (.44 if up else .23), -.27, .97) + beam("Weapon_Bow" + suffix, (weapon_x, -.43, .97), tip, .055, + m["secondary"], vertices=6) + beam("Weapon_String" + suffix, tip, (weapon_x, .02, .97), .011, + m["light"], vertices=4) + _spike("Weapon_Bolt", (weapon_x, -.44, .98), + (weapon_x, -.78 if up else -.66, .98), .052, m["light"]) + if up: + box("Weapon_Sight", (0, -.13, 1.08), (.08, .25, .09), m["primary"]) + _spike("Head_Crest", (0, .03, 1.34), (0, .10, 1.58), .075, + m["secondary"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Arm" + suffix + "_Pauldron", (s * .27, .01, .96), + (.16, .25, .13), m["secondary"]) + + +def _nebel_ranged(up, m): + _mist_robe(m, up) + _mask("Head_Mask", (0, -.105, 1.18), 1.0, m["light"], m["primary"]) + _leaf("Head_Hood", (0, .055, 1.16), .35, .37, m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, 0, .94), (s * .31, -.18, .77), + .055, m["secondary"], vertices=5) + horn_sides = (-1, 1) if up else (1,) + for s in horn_sides: + suffix = "L" if s < 0 else "R" + root = (s * .25, -.12, .79) + elbow = (s * .46, .07, 1.08 if up else .97) + mouth = (s * (.48 if up else .31), -.03, 1.27 if up else 1.02) + beam("Weapon_HornStem" + suffix, root, elbow, .055, m["secondary"]) + beam("Weapon_HornCurve" + suffix, elbow, mouth, .072, m["light"]) + _horn("Weapon_HornBell" + suffix, mouth, .19 if up else .16, + .40 if up else .49, m["light"]) + axis = _unit((0, -1, .18)) + lip = _add(mouth, _mul(axis, .39 if up else .48)) + _lathe("Weapon_MintLip" + suffix, lip, + [(.19 if up else .16, 0), (.19 if up else .16, .025), + (.16 if up else .132, .025), (.16 if up else .132, 0)], + m["accent"], axis) + + +def _wurzel_ranged(up, m): + _root_feet(m["primary"], 3, .34, .56) + ellipsoid("Body_Trunk", (0, .025, .76), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.025, 1.13), (.17, .15, .20), m["secondary"]) + _eyes((0, -.17, 1.13), m["accent"], spread=.057, scale=.03) + _leaf("Body_LeafMantle", (0, -.14, .59), .43, .40, m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + shoulder = (s * .17, 0, .91) + hand = (s * .29, -.21, .85) + beam("Arm" + suffix, shoulder, hand, .07, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .26, -.13, .81), .21, .26, + m["secondary"], lean=s * .1) + beam("Weapon_VineLower", (.28, -.17, .73), (.44, -.08, .93), .046, + m["primary"], vertices=5) + beam("Weapon_VineUpper", (.44, -.08, .93), (.40, -.17, 1.17), .04, + m["primary"], vertices=5) + _cup("Weapon_SeedCapsule", (.24, -.19, .88), .19 if up else .15, + .20, m["accent"], axis=(0, -.7, .7), segments=8) + ellipsoid("Weapon_Seed", (.24, -.30, 1.02), (.075, .075, .10), m["light"]) + if up: + # Overlapping tiers make a pinecone crown, not a mushroom cap. + for layer in range(3): + z = 1.24 + layer * .10 + radius = .23 - layer * .035 + cone("Head_ConeTier" + str(layer), (0, .025, z), radius, + radius * .47, .16, m["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + layer * .3 + _leaf("Head_ConeScale" + str(layer) + "_" + str(k), + (radius * .75 * cos(a), .025 + radius * .75 * sin(a), z - .05), + .11, .16, m["accent"]) + else: + _leaf("Head_LeafCrest", (0, .04, 1.22), .22, .25, m["accent"], .08) + + +def _glut_artillery(up, m): + _basalt_legs(m["primary"], True) + ellipsoid("Body_Foundation", (0, .025, .48), (.39, .31, .22), m["primary"]) + _cup("Weapon_Crater", (0, .02, .52), .55 if up else .43, + .63 if up else .50, m["primary"], segments=12) + _cup("Weapon_EmberLining", (0, .02, .66), .37 if up else .29, + .24 if up else .20, m["secondary"], segments=10) + for s, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Arm" + suffix + "_Slab", (s * .39, .0, .65), + (.13, .19, .25), m["primary"]) + ellipsoid("Head_Eye" + suffix, (s * .13, -.28, .53), + (.055, .025, .035), m["secondary"]) + for k in range(3 if up else 2): + ellipsoid("Weapon_Coal" + str(k), + ((k - (1 if up else .5)) * .12, .015, .80 if up else .77), + (.105, .10, .10), m["accent"]) + if up: + for k in range(5): + a = .2 + pi * k / 4 + _spike("Body_CraterFin" + str(k), + (.40 * cos(a), .03 + .39 * sin(a), .87), + (.46 * cos(a), .03 + .43 * sin(a), 1.37), .095, + m["primary"]) + + +def _nieten_artillery(up, m): + _mechanical_legs(m, True) + box("Body_Chassis", (0, .035, .67), (.56 if up else .45, .37, .34), + m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Piston", (s * .25, .1, .60), + (s * .34, .17, .96), .065, m["accent"]) + cylinder("Arm" + suffix + "_Collar", (s * .31, .15, .84), .095, + .15, m["secondary"], vertices=8) + bell_positions = (-.29, .29) if up else (0,) + for i, x in enumerate(bell_positions): + base = (x, .08, .92) + _horn("Weapon_Resonator" + str(i), base, .27 if up else .34, + .48, m["secondary"], axis=(0, -1, .3)) + # A dark interior cavity and a slim central piston remain visible. + beam("Weapon_Clapper" + str(i), (x, .045, .94), (x, -.26, 1.035), + .038, m["accent"]) + ellipsoid("Weapon_ClapperHead" + str(i), (x, -.27, 1.04), + (.09, .07, .09), m["light"]) + box("Head_Visor", (0, -.164, .68), (.20, .03, .075), m["light"]) + for x, suffix in ((-.24, "L"), (.24, "R")): + cylinder("Body_Exhaust" + suffix, (x, .25, 1.03), .075, + .50 if up else .34, m["accent"], vertices=8) + if up: + box("Body_Brow", (0, -.10, 1.34), (.66, .14, .085), m["primary"]) + cone("Head_Metronome", (0, -.03, 1.47), .10, 0, .20, + m["light"], vertices=4) + + +def _nebel_artillery(up, m): + # Face forward/slightly up: the cavity remains visible to an elevated camera. + _mist_robe(m, up) + bell_base = (0, -.16, 1.05 if up else .85) + radius, depth = (.45, .60) if up else (.38, .50) + _horn("Body_CathedralBell", bell_base, radius, depth, + m["light"], axis=(0, -1, .12)) + beam("Weapon_ClapperStem", (0, -.27, 1.09 if up else .90), + (0, -.70 if up else -.60, 1.0 if up else .80), .045, m["accent"]) + ellipsoid("Weapon_Clapper", (0, -.73 if up else -.63, 1.0 if up else .80), + (.13, .10, .13), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, .02, .96), + (s * .44, -.08, .63), .07, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .44, -.08, .63), + (s * .49, -.19, .94), .10, m["primary"]) + _mask("Head_Mask", (0, .035, 1.49 if up else 1.38), .65, + m["secondary"], m["accent"]) + if up: + for i, x in enumerate((-.27, 0, .27)): + beam("Head_SpireBase" + str(i), (x * .65, .08, 1.16), + (x, .09, 1.42), .075, m["primary"], vertices=5) + _spike("Head_Spire" + str(i), (x, .09, 1.40), + (x * .65, -.01, 1.71 if i == 1 else 1.59), + .075, m["light"]) + + +def _mushroom(name, loc, radius, height, m): + x, y, z = loc + cone(name + "_Stem", (x, y, z + height * .45), .095, .07, height * .9, + m["primary"], vertices=7) + # An angular overhanging cap and light gill ring form a readable roof. + cone(name + "_Gills", (x, y, z + height * .86), radius * .91, + radius * .5, .10, m["accent"], vertices=10) + cone(name + "_Cap", (x, y, z + height), radius, radius * .15, + .22, m["light"], vertices=10) + + +def _wurzel_artillery(up, m): + _root_feet(m["primary"], 5, .50 if up else .43, .56) + ellipsoid("Body_Moss", (0, .02, .48), (.32, .26, .18), m["secondary"]) + _cup("Weapon_SporeChalice", (0, -.10, .50), .40 if up else .43, + .43, m["light"], segments=12) + _cup("Weapon_SporeInterior", (0, -.10, .60), .28, .18, + m["secondary"], segments=10) + for i, x in enumerate((-.105, .105)): + ellipsoid("Weapon_Spore" + str(i), (x, -.08, .81), + (.06, .06, .075), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + _leaf("Arm" + suffix + "_Leaf", (s * .30, -.05, .46), .20, .36, + m["accent"], lean=s * .14) + if up: + _mushroom("Body_RoofL", (-.34, .12, .47), .30, .67, m) + _mushroom("Body_RoofR", (.34, .18, .47), .29, .81, m) + _mushroom("Body_RoofCrown", (0, .33, .54), .39, .98, m) + for x, suffix in ((-.12, "L"), (.12, "R")): + beam("Body_Buttress" + suffix, (x * 3, .33, .12), + (x, .31, 1.21), .075, m["primary"], vertices=5) + + +def _glut_support(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_FurnaceBack", (0, .11, .79), + (.34 if up else .28, .20, .37), m["primary"]) + _cup("Body_OpenHearth", (0, .015, .85), .28 if up else .23, + .33, m["accent"], axis=(0, -1, 0), segments=8) + ellipsoid("Body_Ember", (0, -.10, .85), (.12, .085, .15), m["secondary"]) + ellipsoid("Head_Capstone", (0, .01, 1.17), (.21, .17, .15), m["light"]) + _eyes((0, -.15, 1.16), m["secondary"], spread=.075) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .26, .01, .92), + (s * .33, -.33, .63), .09, m["primary"], vertices=6) + _cup("Weapon_WarmingBowl", (0, -.38, .52), .36 if up else .29, + .22, m["accent"], segments=10) + ellipsoid("Weapon_WarmCoal", (0, -.38, .61), (.15, .12, .07), + m["secondary"]) + if up: + # Upper-half sun rays stay behind the face, safely within the footprint. + for k in range(7): + a = pi * k / 6 + start = (.30 * cos(a), .09, 1.12 + .30 * sin(a)) + end = (.48 * cos(a), .11, 1.12 + .48 * sin(a)) + _spike("Head_SunRay" + str(k), start, end, .065, m["accent"]) + cone("Head_Crown", (0, .0, 1.34), .16, .23, .12, + m["accent"], vertices=8) + + +def _nieten_support(up, m): + _mechanical_legs(m, up) + cone("Body_Coat", (0, .02, .73), .37 if up else .24, + .20, .51, m["primary"], vertices=6) + box("Body_PendulumCase", (0, -.18, .79), (.18, .10, .30), m["secondary"]) + beam("Body_Pendulum", (0, -.24, .89), (.045, -.24, .64), .018, m["accent"]) + ellipsoid("Body_PendulumWeight", (.045, -.24, .65), (.07, .035, .07), + m["light"]) + ellipsoid("Head_Casing", (0, .015, 1.14), (.17, .14, .17), m["accent"]) + ellipsoid("Head_Dial", (0, -.119, 1.14), (.135, .025, .135), m["light"]) + beam("Head_DialHand", (0, -.15, 1.14), (.055, -.15, 1.22), .015, + m["primary"], vertices=4) + for s, suffix in ((-1, "L"), (1, "R")): + elbow = (s * .35, .0, .91) + hand = (s * .45, -.13, 1.10 if s > 0 else .89) + beam("Arm" + suffix + "_Upper", (s * .2, .02, .95), elbow, .06, + m["accent"]) + beam("Arm" + suffix + "_Fore", elbow, hand, .047, m["secondary"]) + ellipsoid("Arm" + suffix + "_Hand", hand, (.065, .065, .065), m["light"]) + beam("Weapon_Baton", (.45, -.13, 1.06), (.61, -.22, 1.45), .019, + m["light"], vertices=5) + if up: + for k, x in enumerate((-.18, 0, .18)): + _spike("Head_CrownTine" + str(k), (x, .015, 1.28), + (x, .015, 1.56 if k == 1 else 1.47), .06, + m["secondary"]) + box("Head_MetronomeBridge", (0, .015, 1.36), (.45, .12, .07), + m["secondary"]) + for s in (-1, 1): + _leaf("Body_CoatTail" + str(s), (s * .20, .20, .33), .24, .59, + m["secondary"], lean=s * .16) + else: + _spike("Head_Spindle", (0, .015, 1.28), (0, .015, 1.45), .055, + m["secondary"]) + + +def _nebel_support(up, m): + _mist_robe(m, up) + _mask("Head_MainMask", (0, -.13, 1.17), 1.0, m["light"], m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Lower", (s * .17, 0, .88), + (s * .37, -.04, .82), .062, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .37, -.04, .82), + (s * .49, -.04, 1.21), .095, m["primary"]) + _leaf("Body_SickleCollar" + suffix, (s * .13, .02, .88), .29, + .43 if up else .29, m["secondary"], lean=s * .29) + if up: + positions = ((-.51, -.035, 1.46), (0, .11, 1.65), (.51, -.035, 1.46)) + for i, p in enumerate(positions): + _mask("Head_CompanionMask" + str(i), p, .67, + m["light"], m["primary"]) + for i, x in enumerate((-.12, 0, .12)): + _spike("Head_Crown" + str(i), (x, -.035, 1.31), + (x * 1.2, -.035, 1.53 if i == 1 else 1.45), .045, + m["accent"]) + else: + _mask("Head_CompanionMask0", (.49, -.035, 1.44), .70, + m["light"], m["primary"]) + ellipsoid("Body_ChoirGem", (0, -.19, .83), (.055, .035, .09), m["accent"]) + + +def _flower(name, loc, scale, m): + for k in range(5): + a = 2 * pi * k / 5 + ellipsoid(name + "_Petal" + str(k), + (loc[0] + cos(a) * .09 * scale, + loc[1] + sin(a) * .09 * scale, loc[2]), + (.085 * scale, .07 * scale, .035 * scale), m["light"]) + ellipsoid(name + "_Heart", (loc[0], loc[1], loc[2] + .025 * scale), + (.052 * scale, .052 * scale, .035 * scale), m["accent"]) + + +def _wurzel_support(up, m): + _root_feet(m["primary"], 5 if up else 3, .45 if up else .31, .55) + # Two counter-leaning stems create an open woven body in the upgrade. + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_WovenRoot" + suffix, (s * .20, .02, .38), + (-s * .17, .015, .83), .105, m["primary"], vertices=5) + beam("Body_WovenRootTop" + suffix, (-s * .17, .015, .83), + (s * .11, .025, 1.16), .085, m["primary"], vertices=5) + else: + ellipsoid("Body_Trunk", (0, .025, .72), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.03, 1.12), (.15, .14, .18), m["secondary"]) + _eyes((0, -.17, 1.12), m["accent"], spread=.05, scale=.026) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .15, 0, .94), + (s * .28, -.27, .69), .065, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .23, -.21, .68), .21, .28, + m["secondary"], lean=s * .12) + _cup("Weapon_LeafBasin", (0, -.31, .62), .30 if up else .23, + .20, m["accent"], segments=8) + # Water uses the optional shared mint accent, with a leaf-colour fallback. + # Opaque faceted geometry avoids sorting issues until the VFX integration. + water = m.get("water", m["accent"]) + cylinder("Weapon_Pool", (0, -.31, .739), .21 if up else .145, + .025, water, vertices=10) + ellipsoid("Weapon_Dew", (0, -.31, .86), (.085, .075, .13), water) + _spike("Weapon_DewTip", (0, -.31, .93), (0, -.31, 1.035), .059, water) + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_CanopyStem" + suffix, (s * .17, .11, .88), + (s * .36, .14, 1.28), .055, m["primary"], vertices=5) + _leaf("Head_Canopy" + suffix, (s * .12, .10, 1.17), .56, .36, + m["secondary"], lean=s * .28) + _flower("Head_Flower" + suffix, (s * .31, .12, 1.43), 1.0, m) + _flower("Head_FlowerCrown", (0, .07, 1.53), .9, m) + else: + _leaf("Head_LeafCap", (0, .02, 1.23), .33, .25, m["accent"], -.06) + + +_RANGED = {"glutpakt": _glut_ranged, "nietenkonvent": _nieten_ranged, + "nebelchor": _nebel_ranged, "wurzelbund": _wurzel_ranged} +_ARTILLERY = {"glutpakt": _glut_artillery, "nietenkonvent": _nieten_artillery, + "nebelchor": _nebel_artillery, "wurzelbund": _wurzel_artillery} +_SUPPORT = {"glutpakt": _glut_support, "nietenkonvent": _nieten_support, + "nebelchor": _nebel_support, "wurzelbund": _wurzel_support} + + +def build_ranged(spec, mat): + """Build IDs *05 (base) and *06 (upgraded).""" + _RANGED[spec["faction"]](spec["upgraded"], mat) + + +def build_artillery(spec, mat): + """Build IDs *07 (base) and *08 (upgraded).""" + _ARTILLERY[spec["faction"]](spec["upgraded"], mat) + + +def build_support(spec, mat): + """Build IDs *09 (base) and *10 (upgraded).""" + _SUPPORT[spec["faction"]](spec["upgraded"], mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_core.py b/assets-source/phase4/standalone/create_core.py new file mode 100644 index 0000000..8b2b82e --- /dev/null +++ b/assets-source/phase4/standalone/create_core.py @@ -0,0 +1,3167 @@ +"""Saumwacht · Teamkerne · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'core_team0' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'core_team0', + 'name': 'Saumkern · Team 0', + 'faction': 'team0', + 'palette': 'team0', + 'role': 'core', + 'team': 0, + 'upgraded': False, + 'height': 2.2, + 'footprint': 3.2, + 'file': 'core_team0.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'core_team1', + 'name': 'Saumkern · Team 1', + 'faction': 'team1', + 'palette': 'team1', + 'role': 'core', + 'team': 1, + 'upgraded': False, + 'height': 2.2, + 'footprint': 3.2, + 'file': 'core_team1.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, pi, sin + + + +def _prism(name, outline, front_y, back_y, material): + """Extrude an X/Z outline along Y, useful for readable masks and wedges.""" + area = sum(outline[i][0] * outline[(i + 1) % len(outline)][1] + - outline[(i + 1) % len(outline)][0] * outline[i][1] + for i in range(len(outline))) + if area < 0: + outline = list(reversed(outline)) + count = len(outline) + vertices = [(x, front_y, z) for x, z in outline] + vertices += [(x, back_y, z) for x, z in outline] + faces = [tuple(range(count)), tuple(range(2 * count - 1, count - 1, -1))] + for i in range(count): + following = (i + 1) % count + faces.append((i, i + count, following + count, following)) + return mesh_object(name, vertices, faces, material) + + +def _figure(spec, nominal_height): + """Scaled primitive wrappers keep species proportions stable at any height.""" + scale = float(spec.get("height", nominal_height)) / nominal_height + + def point(value): + return tuple(component * scale for component in value) + + class Figure: + def box(self, name, loc, size, material, rotation=None): + return box(name, point(loc), point(size), material, rotation=rotation) + + def ellipsoid(self, name, loc, size, material, subdivisions=1): + return ellipsoid(name, point(loc), point(size), material, subdivisions=subdivisions) + + def cylinder(self, name, loc, radius, depth, material, vertices=8, rotation=None): + return cylinder(name, point(loc), radius * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def cone(self, name, loc, radius1, radius2, depth, material, vertices=8, rotation=None): + return cone(name, point(loc), radius1 * scale, radius2 * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def beam(self, name, start, end, radius, material, vertices=6): + return beam(name, point(start), point(end), radius * scale, + material, vertices=vertices) + + def ring(self, name, loc, major_radius, minor_radius, material, + rotation=None, segments=10): + return ring(name, point(loc), major_radius * scale, minor_radius * scale, + material, rotation=rotation, segments=segments) + + def prism(self, name, outline, front_y, back_y, material): + return _prism(name, [(x * scale, z * scale) for x, z in outline], + front_y * scale, back_y * scale, material) + + return Figure() + + +def _boots(f, material, x=0.22, width=0.26, height=0.18, depth=0.42): + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side + "_Boot", (sign * x, -0.075, height / 2), + (width, depth, height), material) + + +def _eyes(f, material, z, y, separation=0.10): + for side, sign in (("L", -1), ("R", 1)): + f.box("Head_Eye" + side, (sign * separation, y, z), + (0.065, 0.025, 0.034), material) + + +def build_lane(spec, mat): + """12 m traversable width, 4 m repeat length, deck at Z=0. + + Side decoration remains strictly outside X=[-6,+6], and nothing extends + past Y=[-2,+2], so consecutive copies meet without a transverse obstacle. + """ + box("Body_LaneFoundation", (0, 0, -0.195), (12, 4, 0.31), mat["primary"]) + for column in range(6): + box("Body_LaneSlab_%02d" % column, (-5 + column * 2, 0, -0.02), + (2, 4, 0.04), mat["primary"]) + for side, sign in (("L", -1), ("R", 1)): + box("Body_" + side + "RetainingLip", (sign * 6.15, 0, -0.10), + (0.30, 4, 0.50), mat["secondary"]) + for index, y in enumerate((-1.42, 0, 1.42)): + ellipsoid("Body_" + side + "Basalt_%02d" % index, + (sign * 6.46, y, -0.05), + (0.26, 0.42, 0.26 if index != 1 else 0.30), mat["secondary"]) + for index, y in enumerate((-1.15, 1.15)): + box("Body_" + side + "BrassMarker_%02d" % index, + (sign * 6.15, y, 0.165), (0.19, 0.20, 0.03), mat["accent"]) + ellipsoid("Body_" + side + "Moss", (sign * 6.39, 0.65, 0.02), + (0.17, 0.34, 0.13), mat["light"]) + empty("Anchor_Deck", (0, 0, 0)) + empty("Anchor_JoinNorth", (0, 2, 0)) + empty("Anchor_JoinSouth", (0, -2, 0)) + + +def build_core(spec, mat): + """A grounded crystal cradle with a physical team circle or triangle.""" + triangular = int(spec.get("team", 0)) == 1 + sides = 3 if triangular else 12 + cylinder("Body_CorePlinth", (0, 0, 0.13), 1.26, 0.26, + mat["primary"], vertices=sides) + cylinder("Body_BrassPlinthRim", (0, 0, 0.285), 1.18, 0.05, + mat["secondary"], vertices=sides) + cylinder("Body_CradleStep", (0, 0, 0.37), 0.85, 0.12, + mat["primary"], vertices=8) + if triangular: + points = [(1.06 * sin(i * 2 * pi / 3), -1.06 * cos(i * 2 * pi / 3), 0.34) + for i in range(3)] + for i in range(3): + beam("Team_Triangle_%d" % i, points[i], points[(i + 1) % 3], + 0.045, mat["accent"], vertices=6) + else: + ring("Team_Circle", (0, 0, 0.345), 1.025, 0.045, mat["accent"], segments=20) + # Multiple low-poly rings create a recognizable mineral, not a sphere. + vertices = [(0, 0, 0.51)] + for radius, z in ((0.37, 0.70), (0.58, 1.16), (0.36, 1.72)): + vertices.extend((radius * cos(i * pi / 3), radius * sin(i * pi / 3), z) + for i in range(6)) + vertices.append((0, 0, 2.20)) + faces = [(0, 1 + (i + 1) % 6, 1 + i) for i in range(6)] + for row in range(2): + start = 1 + 6 * row + for i in range(6): + following = (i + 1) % 6 + faces.append((start + i, start + following, + start + 6 + following, start + 6 + i)) + faces.extend((13 + i, 13 + (i + 1) % 6, 19) for i in range(6)) + mesh_object("Body_CoreCrystal", vertices, faces, mat["accent"]) + for index in range(4): + angle = pi / 4 + index * pi / 2 + x, y = sin(angle), cos(angle) + beam("Arm_Cradle_%d" % index, (x * 0.72, y * 0.72, 0.42), + (x * 0.47, y * 0.47, 0.88), 0.075, mat["secondary"]) + ellipsoid("Arm_CradleClasp_%d" % index, + (x * 0.48, y * 0.48, 0.85), (0.12, 0.12, 0.09), mat["light"]) + empty("Anchor_CoreEffect", (0, 0, 1.25)) + + +def build_worker(spec, mat): + """Small clay Funkenleser with a fork and a framed energy container.""" + f = _figure(spec, 1.1) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.14, depth=0.31) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.16, 0, 0.14), + (sign * 0.15, 0, 0.36), 0.10, mat["primary"]) + f.ellipsoid("Body_Clay", (0, 0, 0.49), (0.30, 0.21, 0.30), mat["primary"]) + f.prism("Body_Apron", [(-0.20, 0.68), (-0.24, 0.30), (0.24, 0.30), (0.20, 0.68)], + -0.23, -0.19, mat["secondary"]) + f.box("Body_Buckle", (0, -0.248, 0.56), (0.10, 0.035, 0.07), mat["accent"]) + f.ellipsoid("Head_Hood", (0, 0.005, 0.88), (0.26, 0.235, 0.22), mat["secondary"]) + f.ellipsoid("Head_ClayFace", (0, -0.175, 0.88), (0.195, 0.10, 0.17), mat["primary"]) + _eyes(f, mat["secondary"], 0.905, -0.274, separation=0.075) + f.beam("ArmL", (-0.23, 0, 0.64), (-0.40, -0.19, 0.52), 0.085, mat["primary"]) + f.beam("ArmR", (0.23, 0, 0.64), (0.39, -0.23, 0.54), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.40, -0.19, 0.52), (0.105, 0.09, 0.09), mat["primary"]) + f.ellipsoid("ArmR_Hand", (0.39, -0.23, 0.54), (0.105, 0.09, 0.09), mat["primary"]) + f.beam("Weapon_SparkForkHandle", (-0.43, -0.20, 0.13), (-0.43, -0.20, 0.78), + 0.032, mat["accent"]) + for sign in (-1, 1): + f.beam("Weapon_SparkForkProng_%d" % sign, (-0.43, -0.20, 0.78), + (-0.43 + sign * 0.10, -0.20, 0.99), 0.026, mat["accent"]) + f.cylinder("Weapon_ContainerBase", (0.44, -0.24, 0.32), 0.11, 0.045, mat["accent"]) + f.cylinder("Weapon_ContainerLid", (0.44, -0.24, 0.61), 0.11, 0.045, mat["accent"]) + # An open brass cage gives glass-like legibility without alpha sorting. + for index in range(4): + angle = index * pi / 2 + f.beam("Weapon_ContainerRib_%d" % index, + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.33), + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.60), + 0.016, mat["accent"], vertices=4) + f.ellipsoid("Weapon_CapturedSpark", (0.44, -0.24, 0.47), + (0.058, 0.058, 0.105), mat["light"]) + + +def _scout(spec, mat): + f = _figure(spec, 1.70) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.18) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.18, 0, 0.17), + (sign * 0.15, 0, 0.78), 0.087, mat["primary"]) + f.box("Leg" + side + "_ShinPlate", (sign * 0.18, -0.095, 0.35), + (0.13, 0.05, 0.24), mat["secondary"]) + f.cone("Body_Armor", (0, 0, 0.97), 0.22, 0.28, 0.49, mat["primary"], vertices=6) + f.box("Body_Belt", (0, 0, 0.77), (0.44, 0.30, 0.10), mat["secondary"]) + f.ellipsoid("Head_Hood", (0, 0.015, 1.42), (0.23, 0.21, 0.25), mat["primary"]) + f.cone("Head_HoodPoint", (0, 0.055, 1.60), 0.145, 0, 0.20, mat["primary"], vertices=5) + f.prism("Head_Mask", [(-0.15, 1.54), (-0.13, 1.32), (0, 1.26), (0.13, 1.32), (0.15, 1.54)], + -0.21, -0.165, mat["light"]) + _eyes(f, mat["primary"], 1.46, -0.225, separation=0.075) + f.beam("ArmL_Upper", (-0.24, 0, 1.12), (-0.34, -0.17, 0.96), 0.078, mat["primary"]) + f.beam("ArmL_Fore", (-0.34, -0.17, 0.96), (-0.06, -0.37, 1.02), 0.071, mat["primary"]) + f.beam("ArmR_Upper", (0.24, 0, 1.12), (0.35, -0.15, 0.97), 0.078, mat["primary"]) + f.beam("ArmR_Fore", (0.35, -0.15, 0.97), (0.25, -0.43, 1.07), 0.071, mat["primary"]) + f.box("Weapon_DartLauncherStock", (0.19, -0.34, 1.07), (0.19, 0.44, 0.15), mat["secondary"]) + f.cylinder("Weapon_DartLauncherBarrel", (0.19, -0.66, 1.09), + 0.065, 0.34, mat["light"], rotation=(pi / 2, 0, 0)) + f.cylinder("Weapon_DartLauncherBore", (0.19, -0.836, 1.09), + 0.04, 0.008, mat["primary"], rotation=(pi / 2, 0, 0)) + f.box("Body_DartQuiver", (-0.14, 0.23, 1.02), (0.23, 0.17, 0.45), mat["secondary"], + rotation=(0, -0.16, 0)) + for index in range(3): + x = -0.23 + index * 0.085 + f.beam("Weapon_SpareDart_%d" % index, (x, 0.24, 1.10), (x - 0.06, 0.24, 1.47), + 0.024, mat["light"], vertices=4) + + +def _ram(spec, mat): + f = _figure(spec, 1.48) + _boots(f, mat["primary"], x=0.27, width=0.35, height=0.20, depth=0.45) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.27, 0, 0.35), (0.25, 0.30, 0.35), mat["primary"]) + f.ellipsoid("Arm" + side + "_Pauldron", (sign * 0.43, 0, 1.05), + (0.27, 0.25, 0.25), mat["secondary"]) + f.box("Body_RustArmor", (0, 0, 0.83), (0.74, 0.48, 0.67), mat["secondary"]) + f.box("Body_UpperLamella", (0, -0.256, 1.01), (0.71, 0.06, 0.18), mat["primary"]) + f.box("Body_LowerLamella", (0, -0.261, 0.80), (0.71, 0.06, 0.16), mat["primary"]) + f.ellipsoid("Head_Helmet", (0, 0, 1.29), (0.27, 0.23, 0.19), mat["primary"]) + f.box("Head_BrowGuard", (0, -0.23, 1.35), (0.45, 0.085, 0.10), mat["light"]) + _eyes(f, mat["accent"], 1.275, -0.235) + f.beam("ArmL", (-0.43, 0, 1.03), (-0.43, -0.40, 0.81), 0.14, mat["primary"]) + f.beam("ArmR", (0.43, 0, 1.03), (0.61, -0.18, 0.72), 0.14, mat["primary"]) + f.box("ArmR_HammerFist", (0.61, -0.19, 0.66), (0.30, 0.28, 0.29), mat["secondary"]) + outline = [(-0.63, 1.09), (-0.68, 0.34), (-0.48, 0.21), (0.45, 0.21), + (0.65, 0.34), (0.60, 1.09)] + f.prism("Weapon_RamShield", outline, -0.54, -0.39, mat["secondary"]) + f.box("Weapon_ShieldTopRim", (-0.015, -0.575, 1.05), (1.18, 0.07, 0.095), mat["light"]) + f.prism("Weapon_CentralWedge", [(-0.13, 0.94), (-0.18, 0.37), (0, 0.28), (0.18, 0.37), (0.13, 0.94)], + -0.74, -0.53, mat["primary"]) + + +def _singer(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.12, depth=0.32) + f.cone("Body_BellRobe", (0, 0, 0.63), 0.43, 0.20, 1.10, mat["primary"], vertices=8) + for index, x in enumerate((-0.22, 0, 0.22)): + f.prism("Body_RobeFold_%d" % index, + [(x - 0.055, 0.15), (x + 0.055, 0.15), (x * 0.45, 1.09)], + -0.32, -0.24, mat["accent"]) + f.ellipsoid("Body_Mantle", (0, 0, 1.24), (0.37, 0.27, 0.21), mat["accent"]) + f.ellipsoid("Head_DeepHood", (0, 0, 1.57), (0.26, 0.25, 0.25), mat["primary"]) + f.prism("Head_SingerMask", [(-0.13, 1.68), (-0.12, 1.47), (0, 1.41), (0.12, 1.47), (0.13, 1.68)], + -0.246, -0.21, mat["light"]) + _eyes(f, mat["primary"], 1.60, -0.257, separation=0.065) + f.beam("ArmL", (-0.29, 0, 1.27), (-0.34, -0.37, 1.05), 0.085, mat["primary"]) + f.beam("ArmR", (0.29, 0, 1.27), (0.36, -0.43, 1.10), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.34, -0.37, 1.05), (0.095, 0.075, 0.075), mat["light"]) + f.ellipsoid("ArmR_Hand", (0.36, -0.43, 1.10), (0.095, 0.075, 0.075), mat["light"]) + f.beam("Weapon_HornPipe", (-0.30, -0.37, 1.08), (0.36, -0.43, 1.13), 0.075, mat["secondary"]) + # A true open bell: two rings connected by a tapered shell, no filled mouth. + vertices = [] + for y, radius in ((-0.43, 0.075), (-0.84, 0.28), (-0.81, 0.235), (-0.47, 0.042)): + for index in range(10): + angle = index * pi / 5 + vertices.append((0.36 + cos(angle) * radius, y, 1.13 + sin(angle) * radius)) + faces = [] + for row in range(3): + for i in range(10): + j = (i + 1) % 10 + faces.append((row * 10 + i, row * 10 + j, (row + 1) * 10 + j, (row + 1) * 10 + i)) + scale = float(spec.get("height", 1.82)) / 1.82 + mesh_object("Weapon_ResonanceHorn", [tuple(v * scale for v in point) for point in vertices], + faces, mat["secondary"]) + f.ring("Weapon_HornRim", (0.36, -0.84, 1.13), 0.258, 0.023, mat["light"], + rotation=(pi / 2, 0, 0)) + + +def _breaker(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.28, width=0.36, height=0.22, depth=0.49) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.26, 0, 0.47), (0.28, 0.31, 0.54), mat["primary"]) + f.box("Leg" + side + "_Knee", (sign * 0.27, -0.19, 0.51), + (0.27, 0.13, 0.24), mat["secondary"]) + f.box("Arm" + side + "_Pauldron", (sign * 0.48, 0, 1.29), + (0.42, 0.52, 0.34), mat["primary"], rotation=(0, sign * 0.14, 0)) + f.cone("Body_SteelTorso", (0, 0, 1.01), 0.35, 0.47, 0.70, mat["primary"], vertices=6) + f.prism("Body_RustChestInset", [(-0.28, 1.29), (0, 0.95), (0.28, 1.29)], + -0.397, -0.35, mat["secondary"]) + f.box("Head_Helmet", (0, 0, 1.61), (0.43, 0.40, 0.42), mat["primary"]) + f.prism("Head_Faceplate", [(-0.17, 1.76), (-0.17, 1.50), (0, 1.44), (0.17, 1.50), (0.17, 1.76)], + -0.23, -0.19, mat["light"]) + f.box("Head_Visor", (0, -0.246, 1.66), (0.25, 0.026, 0.045), mat["primary"]) + f.beam("ArmL", (-0.47, 0, 1.25), (-0.31, -0.50, 0.92), 0.12, mat["primary"]) + f.beam("ArmR", (0.47, 0, 1.25), (0.30, -0.50, 1.20), 0.12, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.31, -0.50, 0.92), (0.145, 0.12, 0.12), mat["secondary"]) + f.ellipsoid("ArmR_Hand", (0.30, -0.50, 1.20), (0.145, 0.12, 0.12), mat["secondary"]) + f.beam("Weapon_HammerShaft", (-0.65, -0.51, 0.77), (0.66, -0.51, 1.36), + 0.055, mat["secondary"]) + f.prism("Weapon_KeilhammerHead", [(0.40, 1.26), (0.43, 1.58), (0.82, 1.80), + (1.02, 1.61), (0.90, 1.18)], + -0.79, -0.24, mat["primary"]) + # Offset along the sloped edge normal; coplanar cap faces would flicker. + f.prism("Weapon_ChiselEdge", [(0.832, 1.814), (1.032, 1.624), (0.992, 1.354), (0.932, 1.644)], + -0.80, -0.23, mat["light"]) + + +def _rift(spec, mat): + f = _figure(spec, 2.08) + _boots(f, mat["primary"], x=0.22, width=0.21, height=0.12, depth=0.35) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side + "_Shin", (sign * 0.22, 0, 0.12), + (sign * 0.30, 0.12, 0.45), 0.069, mat["primary"]) + f.beam("Leg" + side + "_Thigh", (sign * 0.30, 0.12, 0.45), + (sign * 0.17, 0, 0.81), 0.083, mat["primary"]) + f.ellipsoid("Body_Pelvis", (0, 0, 0.83), (0.25, 0.16, 0.16), mat["primary"]) + # Separate ribs bound real negative space; there is deliberately no chest fill. + for side, sign in (("L", -1), ("R", 1)): + f.beam("Body_" + side + "LowerRib", (sign * 0.15, 0, 0.89), + (sign * 0.31, 0, 1.18), 0.095, mat["primary"]) + f.beam("Body_" + side + "UpperRib", (sign * 0.31, 0, 1.18), + (sign * 0.21, 0, 1.52), 0.10, mat["primary"]) + f.beam("Body_" + side + "RiftSeam", (sign * 0.17, -0.080, 0.95), + (sign * 0.245, -0.080, 1.18), 0.019, mat["accent"], vertices=4) + f.beam("Body_" + side + "RiftUpperSeam", (sign * 0.245, -0.080, 1.18), + (sign * 0.16, -0.080, 1.46), 0.019, mat["accent"], vertices=4) + f.beam("Body_Collar", (-0.21, 0, 1.52), (0.21, 0, 1.52), 0.095, mat["primary"]) + f.ellipsoid("Head_HollowShell", (0, 0, 1.73), (0.20, 0.155, 0.23), mat["primary"]) + f.box("Head_RiftMouth", (0, -0.153, 1.69), (0.17, 0.025, 0.043), mat["accent"]) + for index, (x, z) in enumerate(((-0.19, 1.90), (-0.10, 2.02), (0.10, 2.02), (0.19, 1.90))): + f.beam("Head_BrokenCrown_%d" % index, (x, 0, z - 0.13), (x * 1.18, 0, z + 0.06), + 0.038, mat["light"], vertices=5) + f.beam("ArmL_Upper", (-0.30, 0, 1.47), (-0.48, 0.02, 1.13), 0.068, mat["primary"]) + f.beam("ArmL_Fore", (-0.48, 0.02, 1.13), (-0.46, -0.18, 0.77), 0.056, mat["primary"]) + for index in range(3): + f.beam("ArmL_Claw_%d" % index, (-0.50 + index * 0.043, -0.18, 0.79), + (-0.51 + index * 0.049, -0.25, 0.64), 0.020, mat["light"], vertices=4) + f.beam("ArmR_Upper", (0.30, 0, 1.47), (0.49, 0, 1.10), 0.068, mat["primary"]) + f.beam("ArmR_Fore", (0.49, 0, 1.10), (0.37, -0.33, 1.23), 0.056, mat["primary"]) + f.ellipsoid("ArmR_CradlingHand", (0.37, -0.33, 1.23), (0.12, 0.09, 0.052), mat["primary"]) + f.ellipsoid("Weapon_DrainOrb", (0.37, -0.34, 1.40), (0.13, 0.13, 0.13), mat["accent"]) + f.ring("Weapon_DrainOrbit", (0.37, -0.34, 1.40), 0.175, 0.015, + mat["light"], rotation=(0.35, 0.20, 0), segments=10) + + +def build_mercenary(spec, mat): + """Dispatch five neutral mercenaries, retaining recognizable role silhouettes.""" + builders = {"s01": _scout, "s02": _ram, "s03": _singer, + "s04": _breaker, "s05": _rift} + identifier = str(spec["id"]) + if identifier not in builders: + raise ValueError("Unknown Saumwacht mercenary: " + identifier) + builders[identifier](spec, mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_lane.py b/assets-source/phase4/standalone/create_lane.py new file mode 100644 index 0000000..a0d8ce4 --- /dev/null +++ b/assets-source/phase4/standalone/create_lane.py @@ -0,0 +1,3153 @@ +"""Saumwacht · Lane-Segment · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'map_lane_segment' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'map_lane_segment', + 'name': 'Lane-Segment', + 'faction': 'terrain', + 'palette': 'terrain', + 'role': 'lane', + 'upgraded': False, + 'height': 0, + 'file': 'map_lane_segment.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, pi, sin + + + +def _prism(name, outline, front_y, back_y, material): + """Extrude an X/Z outline along Y, useful for readable masks and wedges.""" + area = sum(outline[i][0] * outline[(i + 1) % len(outline)][1] + - outline[(i + 1) % len(outline)][0] * outline[i][1] + for i in range(len(outline))) + if area < 0: + outline = list(reversed(outline)) + count = len(outline) + vertices = [(x, front_y, z) for x, z in outline] + vertices += [(x, back_y, z) for x, z in outline] + faces = [tuple(range(count)), tuple(range(2 * count - 1, count - 1, -1))] + for i in range(count): + following = (i + 1) % count + faces.append((i, i + count, following + count, following)) + return mesh_object(name, vertices, faces, material) + + +def _figure(spec, nominal_height): + """Scaled primitive wrappers keep species proportions stable at any height.""" + scale = float(spec.get("height", nominal_height)) / nominal_height + + def point(value): + return tuple(component * scale for component in value) + + class Figure: + def box(self, name, loc, size, material, rotation=None): + return box(name, point(loc), point(size), material, rotation=rotation) + + def ellipsoid(self, name, loc, size, material, subdivisions=1): + return ellipsoid(name, point(loc), point(size), material, subdivisions=subdivisions) + + def cylinder(self, name, loc, radius, depth, material, vertices=8, rotation=None): + return cylinder(name, point(loc), radius * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def cone(self, name, loc, radius1, radius2, depth, material, vertices=8, rotation=None): + return cone(name, point(loc), radius1 * scale, radius2 * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def beam(self, name, start, end, radius, material, vertices=6): + return beam(name, point(start), point(end), radius * scale, + material, vertices=vertices) + + def ring(self, name, loc, major_radius, minor_radius, material, + rotation=None, segments=10): + return ring(name, point(loc), major_radius * scale, minor_radius * scale, + material, rotation=rotation, segments=segments) + + def prism(self, name, outline, front_y, back_y, material): + return _prism(name, [(x * scale, z * scale) for x, z in outline], + front_y * scale, back_y * scale, material) + + return Figure() + + +def _boots(f, material, x=0.22, width=0.26, height=0.18, depth=0.42): + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side + "_Boot", (sign * x, -0.075, height / 2), + (width, depth, height), material) + + +def _eyes(f, material, z, y, separation=0.10): + for side, sign in (("L", -1), ("R", 1)): + f.box("Head_Eye" + side, (sign * separation, y, z), + (0.065, 0.025, 0.034), material) + + +def build_lane(spec, mat): + """12 m traversable width, 4 m repeat length, deck at Z=0. + + Side decoration remains strictly outside X=[-6,+6], and nothing extends + past Y=[-2,+2], so consecutive copies meet without a transverse obstacle. + """ + box("Body_LaneFoundation", (0, 0, -0.195), (12, 4, 0.31), mat["primary"]) + for column in range(6): + box("Body_LaneSlab_%02d" % column, (-5 + column * 2, 0, -0.02), + (2, 4, 0.04), mat["primary"]) + for side, sign in (("L", -1), ("R", 1)): + box("Body_" + side + "RetainingLip", (sign * 6.15, 0, -0.10), + (0.30, 4, 0.50), mat["secondary"]) + for index, y in enumerate((-1.42, 0, 1.42)): + ellipsoid("Body_" + side + "Basalt_%02d" % index, + (sign * 6.46, y, -0.05), + (0.26, 0.42, 0.26 if index != 1 else 0.30), mat["secondary"]) + for index, y in enumerate((-1.15, 1.15)): + box("Body_" + side + "BrassMarker_%02d" % index, + (sign * 6.15, y, 0.165), (0.19, 0.20, 0.03), mat["accent"]) + ellipsoid("Body_" + side + "Moss", (sign * 6.39, 0.65, 0.02), + (0.17, 0.34, 0.13), mat["light"]) + empty("Anchor_Deck", (0, 0, 0)) + empty("Anchor_JoinNorth", (0, 2, 0)) + empty("Anchor_JoinSouth", (0, -2, 0)) + + +def build_core(spec, mat): + """A grounded crystal cradle with a physical team circle or triangle.""" + triangular = int(spec.get("team", 0)) == 1 + sides = 3 if triangular else 12 + cylinder("Body_CorePlinth", (0, 0, 0.13), 1.26, 0.26, + mat["primary"], vertices=sides) + cylinder("Body_BrassPlinthRim", (0, 0, 0.285), 1.18, 0.05, + mat["secondary"], vertices=sides) + cylinder("Body_CradleStep", (0, 0, 0.37), 0.85, 0.12, + mat["primary"], vertices=8) + if triangular: + points = [(1.06 * sin(i * 2 * pi / 3), -1.06 * cos(i * 2 * pi / 3), 0.34) + for i in range(3)] + for i in range(3): + beam("Team_Triangle_%d" % i, points[i], points[(i + 1) % 3], + 0.045, mat["accent"], vertices=6) + else: + ring("Team_Circle", (0, 0, 0.345), 1.025, 0.045, mat["accent"], segments=20) + # Multiple low-poly rings create a recognizable mineral, not a sphere. + vertices = [(0, 0, 0.51)] + for radius, z in ((0.37, 0.70), (0.58, 1.16), (0.36, 1.72)): + vertices.extend((radius * cos(i * pi / 3), radius * sin(i * pi / 3), z) + for i in range(6)) + vertices.append((0, 0, 2.20)) + faces = [(0, 1 + (i + 1) % 6, 1 + i) for i in range(6)] + for row in range(2): + start = 1 + 6 * row + for i in range(6): + following = (i + 1) % 6 + faces.append((start + i, start + following, + start + 6 + following, start + 6 + i)) + faces.extend((13 + i, 13 + (i + 1) % 6, 19) for i in range(6)) + mesh_object("Body_CoreCrystal", vertices, faces, mat["accent"]) + for index in range(4): + angle = pi / 4 + index * pi / 2 + x, y = sin(angle), cos(angle) + beam("Arm_Cradle_%d" % index, (x * 0.72, y * 0.72, 0.42), + (x * 0.47, y * 0.47, 0.88), 0.075, mat["secondary"]) + ellipsoid("Arm_CradleClasp_%d" % index, + (x * 0.48, y * 0.48, 0.85), (0.12, 0.12, 0.09), mat["light"]) + empty("Anchor_CoreEffect", (0, 0, 1.25)) + + +def build_worker(spec, mat): + """Small clay Funkenleser with a fork and a framed energy container.""" + f = _figure(spec, 1.1) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.14, depth=0.31) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.16, 0, 0.14), + (sign * 0.15, 0, 0.36), 0.10, mat["primary"]) + f.ellipsoid("Body_Clay", (0, 0, 0.49), (0.30, 0.21, 0.30), mat["primary"]) + f.prism("Body_Apron", [(-0.20, 0.68), (-0.24, 0.30), (0.24, 0.30), (0.20, 0.68)], + -0.23, -0.19, mat["secondary"]) + f.box("Body_Buckle", (0, -0.248, 0.56), (0.10, 0.035, 0.07), mat["accent"]) + f.ellipsoid("Head_Hood", (0, 0.005, 0.88), (0.26, 0.235, 0.22), mat["secondary"]) + f.ellipsoid("Head_ClayFace", (0, -0.175, 0.88), (0.195, 0.10, 0.17), mat["primary"]) + _eyes(f, mat["secondary"], 0.905, -0.274, separation=0.075) + f.beam("ArmL", (-0.23, 0, 0.64), (-0.40, -0.19, 0.52), 0.085, mat["primary"]) + f.beam("ArmR", (0.23, 0, 0.64), (0.39, -0.23, 0.54), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.40, -0.19, 0.52), (0.105, 0.09, 0.09), mat["primary"]) + f.ellipsoid("ArmR_Hand", (0.39, -0.23, 0.54), (0.105, 0.09, 0.09), mat["primary"]) + f.beam("Weapon_SparkForkHandle", (-0.43, -0.20, 0.13), (-0.43, -0.20, 0.78), + 0.032, mat["accent"]) + for sign in (-1, 1): + f.beam("Weapon_SparkForkProng_%d" % sign, (-0.43, -0.20, 0.78), + (-0.43 + sign * 0.10, -0.20, 0.99), 0.026, mat["accent"]) + f.cylinder("Weapon_ContainerBase", (0.44, -0.24, 0.32), 0.11, 0.045, mat["accent"]) + f.cylinder("Weapon_ContainerLid", (0.44, -0.24, 0.61), 0.11, 0.045, mat["accent"]) + # An open brass cage gives glass-like legibility without alpha sorting. + for index in range(4): + angle = index * pi / 2 + f.beam("Weapon_ContainerRib_%d" % index, + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.33), + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.60), + 0.016, mat["accent"], vertices=4) + f.ellipsoid("Weapon_CapturedSpark", (0.44, -0.24, 0.47), + (0.058, 0.058, 0.105), mat["light"]) + + +def _scout(spec, mat): + f = _figure(spec, 1.70) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.18) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.18, 0, 0.17), + (sign * 0.15, 0, 0.78), 0.087, mat["primary"]) + f.box("Leg" + side + "_ShinPlate", (sign * 0.18, -0.095, 0.35), + (0.13, 0.05, 0.24), mat["secondary"]) + f.cone("Body_Armor", (0, 0, 0.97), 0.22, 0.28, 0.49, mat["primary"], vertices=6) + f.box("Body_Belt", (0, 0, 0.77), (0.44, 0.30, 0.10), mat["secondary"]) + f.ellipsoid("Head_Hood", (0, 0.015, 1.42), (0.23, 0.21, 0.25), mat["primary"]) + f.cone("Head_HoodPoint", (0, 0.055, 1.60), 0.145, 0, 0.20, mat["primary"], vertices=5) + f.prism("Head_Mask", [(-0.15, 1.54), (-0.13, 1.32), (0, 1.26), (0.13, 1.32), (0.15, 1.54)], + -0.21, -0.165, mat["light"]) + _eyes(f, mat["primary"], 1.46, -0.225, separation=0.075) + f.beam("ArmL_Upper", (-0.24, 0, 1.12), (-0.34, -0.17, 0.96), 0.078, mat["primary"]) + f.beam("ArmL_Fore", (-0.34, -0.17, 0.96), (-0.06, -0.37, 1.02), 0.071, mat["primary"]) + f.beam("ArmR_Upper", (0.24, 0, 1.12), (0.35, -0.15, 0.97), 0.078, mat["primary"]) + f.beam("ArmR_Fore", (0.35, -0.15, 0.97), (0.25, -0.43, 1.07), 0.071, mat["primary"]) + f.box("Weapon_DartLauncherStock", (0.19, -0.34, 1.07), (0.19, 0.44, 0.15), mat["secondary"]) + f.cylinder("Weapon_DartLauncherBarrel", (0.19, -0.66, 1.09), + 0.065, 0.34, mat["light"], rotation=(pi / 2, 0, 0)) + f.cylinder("Weapon_DartLauncherBore", (0.19, -0.836, 1.09), + 0.04, 0.008, mat["primary"], rotation=(pi / 2, 0, 0)) + f.box("Body_DartQuiver", (-0.14, 0.23, 1.02), (0.23, 0.17, 0.45), mat["secondary"], + rotation=(0, -0.16, 0)) + for index in range(3): + x = -0.23 + index * 0.085 + f.beam("Weapon_SpareDart_%d" % index, (x, 0.24, 1.10), (x - 0.06, 0.24, 1.47), + 0.024, mat["light"], vertices=4) + + +def _ram(spec, mat): + f = _figure(spec, 1.48) + _boots(f, mat["primary"], x=0.27, width=0.35, height=0.20, depth=0.45) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.27, 0, 0.35), (0.25, 0.30, 0.35), mat["primary"]) + f.ellipsoid("Arm" + side + "_Pauldron", (sign * 0.43, 0, 1.05), + (0.27, 0.25, 0.25), mat["secondary"]) + f.box("Body_RustArmor", (0, 0, 0.83), (0.74, 0.48, 0.67), mat["secondary"]) + f.box("Body_UpperLamella", (0, -0.256, 1.01), (0.71, 0.06, 0.18), mat["primary"]) + f.box("Body_LowerLamella", (0, -0.261, 0.80), (0.71, 0.06, 0.16), mat["primary"]) + f.ellipsoid("Head_Helmet", (0, 0, 1.29), (0.27, 0.23, 0.19), mat["primary"]) + f.box("Head_BrowGuard", (0, -0.23, 1.35), (0.45, 0.085, 0.10), mat["light"]) + _eyes(f, mat["accent"], 1.275, -0.235) + f.beam("ArmL", (-0.43, 0, 1.03), (-0.43, -0.40, 0.81), 0.14, mat["primary"]) + f.beam("ArmR", (0.43, 0, 1.03), (0.61, -0.18, 0.72), 0.14, mat["primary"]) + f.box("ArmR_HammerFist", (0.61, -0.19, 0.66), (0.30, 0.28, 0.29), mat["secondary"]) + outline = [(-0.63, 1.09), (-0.68, 0.34), (-0.48, 0.21), (0.45, 0.21), + (0.65, 0.34), (0.60, 1.09)] + f.prism("Weapon_RamShield", outline, -0.54, -0.39, mat["secondary"]) + f.box("Weapon_ShieldTopRim", (-0.015, -0.575, 1.05), (1.18, 0.07, 0.095), mat["light"]) + f.prism("Weapon_CentralWedge", [(-0.13, 0.94), (-0.18, 0.37), (0, 0.28), (0.18, 0.37), (0.13, 0.94)], + -0.74, -0.53, mat["primary"]) + + +def _singer(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.12, depth=0.32) + f.cone("Body_BellRobe", (0, 0, 0.63), 0.43, 0.20, 1.10, mat["primary"], vertices=8) + for index, x in enumerate((-0.22, 0, 0.22)): + f.prism("Body_RobeFold_%d" % index, + [(x - 0.055, 0.15), (x + 0.055, 0.15), (x * 0.45, 1.09)], + -0.32, -0.24, mat["accent"]) + f.ellipsoid("Body_Mantle", (0, 0, 1.24), (0.37, 0.27, 0.21), mat["accent"]) + f.ellipsoid("Head_DeepHood", (0, 0, 1.57), (0.26, 0.25, 0.25), mat["primary"]) + f.prism("Head_SingerMask", [(-0.13, 1.68), (-0.12, 1.47), (0, 1.41), (0.12, 1.47), (0.13, 1.68)], + -0.246, -0.21, mat["light"]) + _eyes(f, mat["primary"], 1.60, -0.257, separation=0.065) + f.beam("ArmL", (-0.29, 0, 1.27), (-0.34, -0.37, 1.05), 0.085, mat["primary"]) + f.beam("ArmR", (0.29, 0, 1.27), (0.36, -0.43, 1.10), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.34, -0.37, 1.05), (0.095, 0.075, 0.075), mat["light"]) + f.ellipsoid("ArmR_Hand", (0.36, -0.43, 1.10), (0.095, 0.075, 0.075), mat["light"]) + f.beam("Weapon_HornPipe", (-0.30, -0.37, 1.08), (0.36, -0.43, 1.13), 0.075, mat["secondary"]) + # A true open bell: two rings connected by a tapered shell, no filled mouth. + vertices = [] + for y, radius in ((-0.43, 0.075), (-0.84, 0.28), (-0.81, 0.235), (-0.47, 0.042)): + for index in range(10): + angle = index * pi / 5 + vertices.append((0.36 + cos(angle) * radius, y, 1.13 + sin(angle) * radius)) + faces = [] + for row in range(3): + for i in range(10): + j = (i + 1) % 10 + faces.append((row * 10 + i, row * 10 + j, (row + 1) * 10 + j, (row + 1) * 10 + i)) + scale = float(spec.get("height", 1.82)) / 1.82 + mesh_object("Weapon_ResonanceHorn", [tuple(v * scale for v in point) for point in vertices], + faces, mat["secondary"]) + f.ring("Weapon_HornRim", (0.36, -0.84, 1.13), 0.258, 0.023, mat["light"], + rotation=(pi / 2, 0, 0)) + + +def _breaker(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.28, width=0.36, height=0.22, depth=0.49) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.26, 0, 0.47), (0.28, 0.31, 0.54), mat["primary"]) + f.box("Leg" + side + "_Knee", (sign * 0.27, -0.19, 0.51), + (0.27, 0.13, 0.24), mat["secondary"]) + f.box("Arm" + side + "_Pauldron", (sign * 0.48, 0, 1.29), + (0.42, 0.52, 0.34), mat["primary"], rotation=(0, sign * 0.14, 0)) + f.cone("Body_SteelTorso", (0, 0, 1.01), 0.35, 0.47, 0.70, mat["primary"], vertices=6) + f.prism("Body_RustChestInset", [(-0.28, 1.29), (0, 0.95), (0.28, 1.29)], + -0.397, -0.35, mat["secondary"]) + f.box("Head_Helmet", (0, 0, 1.61), (0.43, 0.40, 0.42), mat["primary"]) + f.prism("Head_Faceplate", [(-0.17, 1.76), (-0.17, 1.50), (0, 1.44), (0.17, 1.50), (0.17, 1.76)], + -0.23, -0.19, mat["light"]) + f.box("Head_Visor", (0, -0.246, 1.66), (0.25, 0.026, 0.045), mat["primary"]) + f.beam("ArmL", (-0.47, 0, 1.25), (-0.31, -0.50, 0.92), 0.12, mat["primary"]) + f.beam("ArmR", (0.47, 0, 1.25), (0.30, -0.50, 1.20), 0.12, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.31, -0.50, 0.92), (0.145, 0.12, 0.12), mat["secondary"]) + f.ellipsoid("ArmR_Hand", (0.30, -0.50, 1.20), (0.145, 0.12, 0.12), mat["secondary"]) + f.beam("Weapon_HammerShaft", (-0.65, -0.51, 0.77), (0.66, -0.51, 1.36), + 0.055, mat["secondary"]) + f.prism("Weapon_KeilhammerHead", [(0.40, 1.26), (0.43, 1.58), (0.82, 1.80), + (1.02, 1.61), (0.90, 1.18)], + -0.79, -0.24, mat["primary"]) + # Offset along the sloped edge normal; coplanar cap faces would flicker. + f.prism("Weapon_ChiselEdge", [(0.832, 1.814), (1.032, 1.624), (0.992, 1.354), (0.932, 1.644)], + -0.80, -0.23, mat["light"]) + + +def _rift(spec, mat): + f = _figure(spec, 2.08) + _boots(f, mat["primary"], x=0.22, width=0.21, height=0.12, depth=0.35) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side + "_Shin", (sign * 0.22, 0, 0.12), + (sign * 0.30, 0.12, 0.45), 0.069, mat["primary"]) + f.beam("Leg" + side + "_Thigh", (sign * 0.30, 0.12, 0.45), + (sign * 0.17, 0, 0.81), 0.083, mat["primary"]) + f.ellipsoid("Body_Pelvis", (0, 0, 0.83), (0.25, 0.16, 0.16), mat["primary"]) + # Separate ribs bound real negative space; there is deliberately no chest fill. + for side, sign in (("L", -1), ("R", 1)): + f.beam("Body_" + side + "LowerRib", (sign * 0.15, 0, 0.89), + (sign * 0.31, 0, 1.18), 0.095, mat["primary"]) + f.beam("Body_" + side + "UpperRib", (sign * 0.31, 0, 1.18), + (sign * 0.21, 0, 1.52), 0.10, mat["primary"]) + f.beam("Body_" + side + "RiftSeam", (sign * 0.17, -0.080, 0.95), + (sign * 0.245, -0.080, 1.18), 0.019, mat["accent"], vertices=4) + f.beam("Body_" + side + "RiftUpperSeam", (sign * 0.245, -0.080, 1.18), + (sign * 0.16, -0.080, 1.46), 0.019, mat["accent"], vertices=4) + f.beam("Body_Collar", (-0.21, 0, 1.52), (0.21, 0, 1.52), 0.095, mat["primary"]) + f.ellipsoid("Head_HollowShell", (0, 0, 1.73), (0.20, 0.155, 0.23), mat["primary"]) + f.box("Head_RiftMouth", (0, -0.153, 1.69), (0.17, 0.025, 0.043), mat["accent"]) + for index, (x, z) in enumerate(((-0.19, 1.90), (-0.10, 2.02), (0.10, 2.02), (0.19, 1.90))): + f.beam("Head_BrokenCrown_%d" % index, (x, 0, z - 0.13), (x * 1.18, 0, z + 0.06), + 0.038, mat["light"], vertices=5) + f.beam("ArmL_Upper", (-0.30, 0, 1.47), (-0.48, 0.02, 1.13), 0.068, mat["primary"]) + f.beam("ArmL_Fore", (-0.48, 0.02, 1.13), (-0.46, -0.18, 0.77), 0.056, mat["primary"]) + for index in range(3): + f.beam("ArmL_Claw_%d" % index, (-0.50 + index * 0.043, -0.18, 0.79), + (-0.51 + index * 0.049, -0.25, 0.64), 0.020, mat["light"], vertices=4) + f.beam("ArmR_Upper", (0.30, 0, 1.47), (0.49, 0, 1.10), 0.068, mat["primary"]) + f.beam("ArmR_Fore", (0.49, 0, 1.10), (0.37, -0.33, 1.23), 0.056, mat["primary"]) + f.ellipsoid("ArmR_CradlingHand", (0.37, -0.33, 1.23), (0.12, 0.09, 0.052), mat["primary"]) + f.ellipsoid("Weapon_DrainOrb", (0.37, -0.34, 1.40), (0.13, 0.13, 0.13), mat["accent"]) + f.ring("Weapon_DrainOrbit", (0.37, -0.34, 1.40), 0.175, 0.015, + mat["light"], rotation=(0.35, 0.20, 0), segments=10) + + +def build_mercenary(spec, mat): + """Dispatch five neutral mercenaries, retaining recognizable role silhouettes.""" + builders = {"s01": _scout, "s02": _ram, "s03": _singer, + "s04": _breaker, "s05": _rift} + identifier = str(spec["id"]) + if identifier not in builders: + raise ValueError("Unknown Saumwacht mercenary: " + identifier) + builders[identifier](spec, mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_melee.py b/assets-source/phase4/standalone/create_melee.py new file mode 100644 index 0000000..887e7e9 --- /dev/null +++ b/assets-source/phase4/standalone/create_melee.py @@ -0,0 +1,3427 @@ +"""Saumwacht · Nahkämpfer · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'g01' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'g01', + 'name': 'Kohlenbeißer', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'melee', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_g01.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'g02', + 'name': 'Schlackenklaue', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'melee', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_g02.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'm03', + 'name': 'Scherschreiter', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'melee', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_m03.glb'}, + {'id': 'm04', + 'name': 'Sechsklingler', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'melee', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_m04.glb'}, + {'id': 'n03', + 'name': 'Fadentänzer', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'melee', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_n03.glb'}, + {'id': 'n04', + 'name': 'Saumzertrenner', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'melee', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_n04.glb'}, + {'id': 'w01', + 'name': 'Dornhopser', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'melee', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_w01.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'w02', + 'name': 'Rankenschnapper', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'melee', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_w02.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, sin, pi + + + +def _profile(name, points, y, depth, mat): + """Extrude a silhouette with outward normals and a centred editable origin.""" + signed_area = sum(points[i][0] * points[(i+1) % len(points)][1] + - points[(i+1) % len(points)][0] * points[i][1] + for i in range(len(points))) + if signed_area < 0: + points = list(reversed(points)) + center_x = (min(p[0] for p in points) + max(p[0] for p in points)) / 2 + center_z = (min(p[1] for p in points) + max(p[1] for p in points)) / 2 + n = len(points) + vertices = [(x-center_x, -depth/2, z-center_z) for x, z in points] + vertices += [(x-center_x, depth/2, z-center_z) for x, z in points] + faces = [tuple(range(n)), tuple(range(2 * n - 1, n - 1, -1))] + faces += [(i, i + n, (i + 1) % n + n, (i + 1) % n) for i in range(n)] + obj = mesh_object(name, vertices, faces, mat) + obj.location = (center_x, y, center_z) + return obj + + +def _slab(name, loc, size, mat, bevel=0.08): + """Eight-sided shield / armour plate with real clipped corners.""" + x, y, z = loc + w, d, h = size + a, b = w / 2, h / 2 + c = min(bevel, a * 0.42, b * 0.42) + points = [(x-a+c, z-b), (x+a-c, z-b), (x+a, z-b+c), + (x+a, z+b-c), (x+a-c, z+b), (x-a+c, z+b), + (x-a, z+b-c), (x-a, z-b+c)] + return _profile(name, points, y, d, mat) + + +def _blade(name, origin, length, width, angle, mat, depth=0.055, hook=0.12): + """A broad bent blade, with an unmistakable edge rather than a thin rod.""" + x, y, z = origin + local = [(-width*.38, 0), (width*.48, 0), + (width*.54, length*.52), (hook, length), + (-width*.30, length*.65)] + points = [(x + u*cos(angle) + v*sin(angle), + z - u*sin(angle) + v*cos(angle)) for u, v in local] + return _profile(name, points, y, depth, mat) + + +def _crescent(name, origin, radius, thickness, start, end, mat, + depth=0.09, segments=10): + """An open polygonal crescent plate in the front plane, angles in radians.""" + x, y, z = origin + angles = [start + (end-start)*i/segments for i in range(segments+1)] + points = [(x + radius*cos(a), z + radius*sin(a)) for a in angles] + points += [(x + (radius-thickness)*cos(a), + z + (radius-thickness)*sin(a)) for a in reversed(angles)] + return _profile(name, points, y, depth, mat) + + +def _eyes(prefix, x, y, z, spacing, mat, width=0.085): + for side, s in (("L", -1), ("R", 1)): + box(prefix + "Eye" + side, (x+s*spacing, y, z), + (width, 0.023, 0.028), mat) + + +def _stone_legs(mat, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (0.27 if upgraded else 0.24) + _slab("Leg" + side + "Shin", (x, 0.02, 0.26), + (0.30, 0.31, 0.36), mat["primary"]) + _slab("Leg" + side + "Foot", (x, -0.10, 0.095), + (0.37, 0.46, 0.19), mat["primary"], 0.07) + if upgraded: + box("Leg" + side + "Cuff", (x, -0.167, 0.27), + (0.23, 0.035, 0.07), mat["accent"]) + + +def _coal_body(mat, upgraded): + ellipsoid("BodyCoal", (0, 0.01, 0.77), (0.44, 0.35, 0.48), + mat["primary"], subdivisions=2) + _slab("BodyForehead", (0, -0.16, 1.115), (0.62, 0.36, 0.25), + mat["primary"]) + mouth = [(-.31,.83), (-.23,.77), (-.12,.80), (0,.735), + (.13,.785), (.24,.76), (.31,.83), (.25,.94), + (.1,.92), (0,.97), (-.14,.93), (-.27,.955)] + _profile("HeadEmberMouth", mouth, -.352, .045, mat["secondary"]) + _eyes("Head", 0, -.350, 1.05, .155, mat["secondary"], .065) + for i, x in enumerate((-.20, 0, .20)): + _profile("HeadTooth%02d" % i, + [(x-.035,.94), (x,.865), (x+.035,.94)], + -.384, .025, mat["light"]) + for side, s in (("L", -1), ("R", 1)): + if upgraded: + _slab("BodyShoulder" + side, (s*.49, .0, 1.08), + (.39, .47, .32), mat["primary"]) + _blade("BodyShoulderCrest" + side, (s*.42, .035, 1.15), + .29, .16, s*.50, mat["primary"], .17, s*.04) + box("BodyShoulderSeam" + side, (s*.50, -.243, 1.05), + (.22, .02, .055), mat["secondary"]) + else: + ellipsoid("BodyShoulder" + side, (s*.41, .02, .87), + (.19, .25, .25), mat["primary"]) + + +def _coal_claws(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Upper", (s*.37, .0, .86), + (s*.55, -.075, .65), .13, mat["primary"]) + ellipsoid("Arm" + side + "Fist", (s*.57, -.16, .56), + (.19, .24, .19), mat["primary"]) + for i, dx in enumerate((-.105, .105)): + x = s*.57 + dx + # Curved front claws are separate wedges; upgrade adds long tips. + points = [(x-.045,.60), (x+.045,.60), (x+.065,.42), + (x+.015,.30 if upgraded else .37), + (x-.035,.43)] + _profile("Weapon" + side + "Claw%02d" % i, points, + -.39 if upgraded else -.34, .115, + mat["accent"] if upgraded else mat["light"]) + if upgraded: + _slab("Arm" + side + "WristGuard", (s*.57, -.18, .70), + (.33, .40, .13), mat["accent"], .045) + + +def _basalt_body(mat, upgraded): + _slab("BodyBastion", (0, .035, .83), + (1.02 if upgraded else .87, .57, .95), mat["primary"]) + _slab("BodyFrontShield", (0, -.30, .80), (.74, .18, .71), + mat["primary"], .14) + _slab("HeadFurnaceSlot", (0, -.401, 1.07), (.48, .035, .085), + mat["secondary"], .025) + for s in (-1, 1): + beam("BodyBrace" + ("L" if s < 0 else "R"), + (s*.29, -.398, .50), (s*.29, -.398, .95), + .033, mat["accent"], vertices=4) + if upgraded: + for i, (x, z, width) in enumerate(((-.48, 1.20, .31), + (0, 1.30, .43), + (.48, 1.20, .31))): + _slab("BodyBattlement%02d" % i, (x, .035, z), + (width, .54, .35), mat["primary"], .05) + box("BodyBattlementCap%02d" % i, (x, .035, z+.145), + (width+.025, .565, .055), mat["accent"]) + _slab("BodyShieldBoss", (0, -.41, .73), (.38, .075, .35), + mat["accent"], .095) + _slab("BodyShieldCore", (0, -.456, .73), (.23, .025, .22), + mat["secondary"], .065) + + +def _basalt_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + x = s * (.635 if upgraded else .54) + _slab("Arm" + side + "Pillar", (x, .01, .72), + (.28, .37, .60), mat["primary"]) + _slab("Arm" + side + "Fist", (x, -.075, .48), + (.32, .42, .27), mat["primary"]) + box("Arm" + side + "Band", (x, -.287, .52), + (.23, .028, .07), mat["accent"]) + + +def _machine_legs(mat, upgraded=False, tall=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (.25 if tall else .24) + top = .72 if tall else .46 + knee = (x*1.15, .03, .38 if tall else .25) + ankle = (x, -.065, .13) + beam("Leg" + side + "PistonUpper", (x*.8, .035, top), knee, + .07 if tall else .13, mat["accent"]) + beam("Leg" + side + "PistonLower", knee, ankle, + .055 if tall else .09, mat["accent"]) + cylinder("Leg" + side + "Knee", knee, .085 if tall else .13, + .16, mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + _slab("Leg" + side + "Shoe", (x, -.105, .065), + (.23 if tall else .33, .36, .13), mat["primary"], .04) + if upgraded: + _slab("Leg" + side + "Greave", (x, -.115, .25), + (.17 if tall else .27, .12, .23), mat["primary"], .04) + + +def _machine_mask(mat, z=1.22): + _profile("HeadCeramicMask", [(-.14,z-.11), (.14,z-.11), + (.17,z+.06), (0,z+.18), (-.17,z+.06)], + -.205, .12, mat["light"]) + _eyes("Head", 0, -.272, z+.025, .067, mat["primary"], .060) + + +def _shear_body(mat, upgraded): + ellipsoid("BodySpindle", (0, .02, .91), + (.285 if upgraded else .21, .235, .32), mat["primary"]) + cylinder("BodyOcherHub", (0, -.224, .87), .14, .07, + mat["secondary"], vertices=10, rotation=(pi/2, 0, 0)) + cylinder("BodyHubPin", (0, -.267, .87), .057, .025, + mat["accent"], vertices=8, rotation=(pi/2, 0, 0)) + _machine_mask(mat, 1.235) + if upgraded: + _slab("BodyHubArmor", (0, .15, .98), (.57, .21, .37), + mat["primary"]) + cone("HeadFin", (0, .055, 1.385), .065, 0, .21, + mat["secondary"], vertices=4) + + +def _shear_weapons(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + if upgraded: + for i, (z, angle) in enumerate(((1.10, .62), (.89, 1.32), + (.66, 2.07))): + pivot = (s*.47, -.105, z) + beam("Arm" + side + "Link%02d" % i, + (s*.21, .02, .93), pivot, .049, mat["secondary"]) + cylinder("Arm" + side + "Hub%02d" % i, pivot, .076, + .10, mat["secondary"], vertices=8, + rotation=(pi/2, 0, 0)) + _blade("Weapon" + side + "Blade%02d" % i, + (pivot[0], -.17, z), .39, .105, s*angle, + mat["accent"], .055, s*.07) + else: + pivot = (s*.43, -.12, .95) + beam("Arm" + side + "Upper", (s*.16, .025, 1.0), + (s*.34, .04, .82), .065, mat["secondary"]) + beam("Arm" + side + "Forearm", (s*.34, .04, .82), + pivot, .060, mat["primary"]) + for i, angle in enumerate((.39, 1.07)): + _blade("Weapon" + side + "Shear%02d" % i, + (pivot[0], -.19-i*.045, pivot[2]), .42, .10, + s*angle, mat["accent"], .055, s*.035) + cylinder("Weapon" + side + "ShearPivot", (s*.43, -.264, .95), + .092, .055, mat["secondary"], vertices=10, + rotation=(pi/2, 0, 0)) + + +def _boiler_body(mat, upgraded): + cylinder("BodyBoiler", (0, .01, .77), .385, .66, + mat["primary"], vertices=12) + cone("BodyBoilerLid", (0, .01, 1.115), .39, .27, .14, + mat["primary"], vertices=12) + ring("BodyLowerRim", (0, .01, .475), .38, .035, + mat["secondary"], segments=12) + _slab("HeadCeramicFace", (0, -.355, .98), (.32, .105, .19), + mat["light"], .04) + _eyes("Head", 0, -.414, 1.005, .074, mat["primary"], .060) + cylinder("BodyGaugeRim", (0, -.402, .695), .117, .07, + mat["secondary"], vertices=12, rotation=(pi/2, 0, 0)) + cylinder("BodyGaugeFace", (0, -.444, .695), .085, .016, + mat["light"], vertices=12, rotation=(pi/2, 0, 0)) + beam("BodyGaugeNeedle", (0, -.458, .695), (.047, -.458, .747), + .012, mat["primary"], vertices=4) + if upgraded: + _slab("BodyChestArmor", (0, -.10, .82), (.81, .55, .61), + mat["primary"], .12) + # Face and gauge sit ahead of the armour, never buried inside it. + for side, s in (("L", -1), ("R", 1)): + cylinder("BodyPressureCylinder" + side, (s*.48, .06, 1.075), + .145, .54, mat["primary"], vertices=10) + cylinder("BodyPressureCap" + side, (s*.48, .06, 1.36), + .16, .07, mat["secondary"], vertices=10) + beam("BodyPressurePipe" + side, (s*.48, .13, .84), + (s*.30, .25, .66), .048, mat["accent"]) + box("HeadBrow", (0, -.37, 1.12), (.46, .17, .09), mat["light"]) + else: + cylinder("BodyChimney", (.235, .10, 1.245), .08, .23, + mat["accent"], vertices=8) + cylinder("BodyChimneyLip", (.235, .10, 1.365), .10, .045, + mat["secondary"], vertices=8) + + +def _boiler_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Piston", (s*.33, .0, .88), + (s*.52, -.02, .63), .09, mat["accent"]) + _slab("Arm" + side + "Fist", (s*.53, -.11, .53), + (.29, .34, .28), mat["accent"], .045) + if upgraded and side == "L": + _slab("WeaponLPressureShield", (-.57, -.245, .75), + (.37, .20, .69), mat["primary"], .08) + _slab("WeaponLShieldStripe", (-.57, -.356, .75), + (.085, .025, .50), mat["secondary"], .025) + elif upgraded: + cylinder("WeaponRPistonCap", (.55, -.302, .59), .165, .08, + mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + + +def _mist_legs(mat, tall=False, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + hip = (s*.12, .045, .71 if tall else .48) + knee = (s*.25, .06 if side == "L" else -.04, .32) + ankle = (s*.20, -.12 if side == "L" else .02, .095) + beam("Leg" + side + "FoldUpper", hip, knee, + .10 if tall else .13, mat["primary"], vertices=5) + beam("Leg" + side + "FoldLower", knee, ankle, .075, + mat["secondary"], vertices=5) + _profile("Leg" + side + "TendrilFoot", + [(s*.20-.09,.035), (s*.20+.11,.035), + (s*.20+.07,.14), (s*.20-.045,.20)], + ankle[1]-.045, .20, mat["primary"]) + + +def _mist_mask(mat, z, large=False): + sx, sz = (.235, .29) if large else (.158, .218) + ellipsoid("HeadMistMask", (0, -.17, z), (sx, .105, sz), + mat["light"], subdivisions=2) + _eyes("Head", 0, -.273, z+.035, sx*.43, mat["accent"], sx*.42) + _profile("HeadMaskChin", [(-sx*.50,z-.10), (0,z-sz*.92), + (sx*.50,z-.10)], -.252, .022, mat["light"]) + + +def _dancer_body(mat, upgraded): + _profile("BodyFoldedRibbon", [(-.16,.56), (.10,.60), (.205,.97), + (.105,1.16), (-.06,1.13), (-.195,.86)], + .025, .27, mat["primary"]) + _profile("BodyVioletFold", [(-.145,.64), (-.04,.67), (.15,1.075), + (.05,1.12)], -.13, .038, mat["secondary"]) + _mist_mask(mat, 1.23) + if upgraded: + _crescent("HeadCrescentCrest", (0, .005, 1.37), .20, .065, + .08*pi, .92*pi, mat["secondary"], .075, 8) + _blade("BodyBackRibbonL", (-.12,.15,.94), .40, .13, -.9, + mat["secondary"], .06, -.05) + _blade("BodyBackRibbonR", (.12,.15,.94), .40, .13, .9, + mat["secondary"], .06, .05) + + +def _dancer_weapons(mat, upgraded): + if upgraded: + # One large open scissor: two distinct sweeping blades at one mint hub. + pivot = (.19, -.32, .79) + beam("ArmLUpper", (-.14,.015,1.05), (-.33,-.11,.85), + .065, mat["secondary"], vertices=5) + beam("ArmLForearm", (-.33,-.11,.85), pivot, + .061, mat["primary"], vertices=5) + beam("ArmRUpper", (.14,.015,1.05), (.36,-.12,.96), + .065, mat["primary"], vertices=5) + beam("ArmRForearm", (.36,-.12,.96), pivot, + .061, mat["secondary"], vertices=5) + _blade("WeaponScissorUpper", pivot, .69, .18, .57, + mat["light"], .075, .09) + _blade("WeaponScissorLower", (.19,-.405,.79), .66, .18, 1.42, + mat["light"], .075, .04) + ring("WeaponScissorHandleL", (.04,-.37,.655), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + ring("WeaponScissorHandleR", (-.005,-.37,.79), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + cylinder("WeaponScissorMintPivot", (.19,-.463,.79), .087, .028, + mat["accent"], vertices=12, rotation=(pi/2,0,0)) + else: + for side, s, high in (("L", -1, False), ("R", 1, True)): + elbow = (s*.31, -.04, .91 if high else .80) + wrist = (s*.43, -.12, 1.07 if high else .66) + beam("Arm" + side + "Upper", (s*.14,.01,1.02), elbow, + .065, mat["primary"], vertices=5) + beam("Arm" + side + "Forearm", elbow, wrist, + .052, mat["secondary"], vertices=5) + _blade("Weapon" + side + "ThreadBlade", wrist, + .40, .065, s*(.50 if high else 2.12), + mat["light"], .045, s*.045) + cylinder("Weapon" + side + "MintGrip", wrist, .060, .09, + mat["accent"], vertices=8, rotation=(pi/2,0,0)) + + +def _mist_tank_body(mat, upgraded): + ellipsoid("BodyFoldedMist", (0,.035,.73), (.37,.25,.44), + mat["primary"], subdivisions=2) + _profile("BodyVioletCenterFold", [(-.22,.43), (.035,.39), + (.25,.90), (.04,1.09)], + -.205, .060, mat["secondary"]) + _mist_mask(mat, 1.145, large=True) + _crescent("BodyFrontCrescent", (0,-.32,.89), .44, .145, + .98*pi, 2.02*pi, mat["secondary"], .15, 12) + if upgraded: + _crescent("BodyOuterShield", (0,-.245,.99), .655, .17, + .89*pi, 2.11*pi, mat["light"], .15, 12) + _crescent("BodyRearShield", (0,.11,1.025), .60, .16, + .05*pi, .95*pi, mat["secondary"], .17, 12) + for side, s in (("L",-1),("R",1)): + _blade("BodyShieldWing" + side, (s*.44,.005,.72), + .49,.23,s*.39,mat["secondary"],.16,s*.10) + _blade("BodyShieldMintEdge" + side, (s*.49,-.09,.79), + .31,.047,s*.39,mat["accent"],.025,s*.065) + + +def _mist_tank_arms(mat, upgraded): + for side, s in (("L",-1),("R",1)): + beam("Arm" + side + "Fold", (s*.31,.005,.92), + (s*.43,-.045,.67), .080, mat["primary"], vertices=5) + _crescent("Arm" + side + "Crescent", (s*.42,-.14,.72), + .24,.075, -.4*pi if s < 0 else .6*pi, + .6*pi if s < 0 else 1.6*pi, + mat["secondary"],.095,8) + + +def _root_legs(mat, upgraded=False, four=False, spread=.32): + positions = [("L", -1, -.035), ("R", 1, -.035)] + if four: + positions = [("LFront",-1,-.27),("RFront",1,-.27), + ("LRear",-1,.28),("RRear",1,.28)] + for label, s, y in positions: + beam("Leg" + label + "Root", (s*spread*.65,y,.48), + (s*spread,y-.035,.13), .11 if four else .13, + mat["primary"], vertices=6) + _slab("Leg" + label + "Foot", (s*spread,y-.10,.075), + (.28,.36,.15), mat["primary"], .065) + # One broad toe root is stronger at gameplay scale than many twigs. + beam("Leg" + label + "Toe", (s*spread,y-.12,.095), + (s*spread+s*.06,y-.31,.055), .045, + mat["accent"], vertices=5) + + +def _leaf(name, origin, length, width, angle, mat, depth=.055): + x,y,z = origin + local = [(0,0),(width*.55,length*.44),(0,length), + (-width*.55,length*.44)] + points = [(x+u*cos(angle)+v*sin(angle), + z-u*sin(angle)+v*cos(angle)) for u,v in local] + return _profile(name,points,y,depth,mat) + + +def _thorn_body(mat, upgraded): + if upgraded: + ellipsoid("BodyCoiledRoot", (0,.08,.63), (.48,.34,.39), + mat["primary"],subdivisions=2) + ring("BodyRootCoil", (0,.065,.61), .365,.085, + mat["primary"],segments=10) + ellipsoid("HeadUpperJaw", (0,-.16,1.07), (.55,.34,.26), + mat["primary"],subdivisions=2) + _slab("HeadLowerJaw", (0,-.265,.66), (.87,.44,.22), + mat["primary"],.085) + _slab("HeadMouthDepth", (0,-.26,.84), (.78,.20,.28), + mat["secondary"],.08) + for i,x in enumerate((-.30,-.10,.10,.30)): + _profile("WeaponUpperFang%02d" % i, + [(x-.065,1.04),(x,.835),(x+.065,1.04)], + -.485,.055,mat["accent"]) + for i,x in enumerate((-.23,0,.23)): + _profile("WeaponLowerFang%02d" % i, + [(x-.07,.74),(x+.07,.74),(x,.91)], + -.497,.055,mat["accent"]) + for side,s in (("L",-1),("R",1)): + _leaf("HeadCheekLeaf" + side,(s*.40,-.29,.82),.39,.29, + s*.59,mat["secondary"],.11) + _leaf("HeadCrownLeaf" + side,(s*.15,.01,1.21),.23,.15, + s*.67,mat["accent"]) + _eyes("Head",0,-.425,1.155,.24,mat["accent"],.09) + else: + ellipsoid("BodyThornPod", (0,.03,.76), (.43,.34,.43), + mat["primary"],subdivisions=2) + _slab("HeadSlit",(0,-.308,.87),(.29,.045,.075),mat["secondary"],.025) + _eyes("Head",0,-.337,.96,.105,mat["accent"],.055) + for side,s in (("L",-1),("R",1)): + _leaf("HeadSprout" + side,(s*.10,.025,1.09),.31,.19, + s*.55,mat["secondary"],.07) + _blade("WeaponSideThorn" + side,(s*.34,.02,.76), + .24,.13,s*1.36,mat["secondary"],.13,s*.015) + for i,(x,y,z) in enumerate(((-.22,-.08,1.07),(.22,-.08,1.07), + (0,.285,.90))): + cone("BodyThorn%02d" % i,(x,y,z),.09,0,.25, + mat["accent"],vertices=5) + + +def _bark_head(mat, upgraded): + ellipsoid("HeadLowRoot", (0,-.36,.50), (.24,.23,.18), + mat["primary"]) + _eyes("Head",0,-.559,.54,.097,mat["accent"],.077) + if upgraded: + _slab("HeadBrowBark",(0,-.43,.68),(.55,.23,.14), + mat["primary"],.045) + + +def _bark_shell(mat, upgraded): + ellipsoid("BodyCorkShell", (0,.07,.80), (.57,.49,.49), + mat["primary"],subdivisions=2) + if upgraded: + # Three actual layered trunk cross sections, readable from above/front. + for index,(x,y,z,r) in enumerate(((0,-.345,.91,.42), + (-.42,.06,.99,.32), + (.42,.06,.99,.32))): + cylinder("BodyGrowthShield%02d" % index,(x,y,z),r,.17, + mat["primary"],vertices=12,rotation=(pi/2,0,0)) + for band,ratio in enumerate((.80,.50)): + ring("BodyGrowthRing%02d_%02d" % (index,band), + (x,y-.097,z),r*ratio,.022, + mat["accent"],rotation=(pi/2,0,0),segments=12) + cylinder("BodyGrowthHeart%02d" % index,(x,y-.099,z),r*.18,.02, + mat["secondary"],vertices=8,rotation=(pi/2,0,0)) + _leaf("BodyCrownLeafL",(-.09,.16,1.19),.25,.19,-.67, + mat["secondary"],.055) + _leaf("BodyCrownLeafR",(.09,.16,1.19),.25,.19,.67, + mat["accent"],.055) + else: + # Asymmetric overlapping cork plates make a turtle-like living shield. + for i,(x,y,z,w,h) in enumerate(((-.26,-.015,1.04,.39,.36), + (.18,-.07,1.11,.42,.31), + (0,.245,.93,.53,.39))): + _slab("BodyCorkPlate%02d" % i,(x,y,z),(w,.29,h), + mat["primary"],.08) + _leaf("BodyMossPlateL",(-.39,-.065,.87),.24,.20,-.49, + mat["secondary"],.08) + _leaf("BodyMossPlateR",(.31,.04,1.06),.20,.19,.57, + mat["secondary"],.06) + + +def _faction(spec): + faction = str(spec["faction"]).lower() + aliases = {"g":"glutpakt", "m":"nietenkonvent", "n":"nebelchor", + "w":"wurzelbund"} + return aliases.get(faction, faction) + + +def build_melee(spec, mat): + """Build a faction-specific melee unit or its visibly evolved upgrade.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _coal_body(mat, upgraded) + _coal_claws(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded, tall=True) + _shear_body(mat, upgraded) + _shear_weapons(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, tall=True, upgraded=upgraded) + _dancer_body(mat, upgraded) + _dancer_weapons(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=upgraded, spread=.34 if upgraded else .27) + _thorn_body(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht melee faction: " + faction) + + +def build_tank(spec, mat): + """Build a tank; upgrades add fortress tiers, pressure shields or growth rings.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _basalt_body(mat, upgraded) + _basalt_arms(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded) + _boiler_body(mat, upgraded) + _boiler_arms(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, upgraded=upgraded) + _mist_tank_body(mat, upgraded) + _mist_tank_arms(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=True, spread=.38 if upgraded else .33) + _bark_shell(mat, upgraded) + _bark_head(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht tank faction: " + faction) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_mercenary.py b/assets-source/phase4/standalone/create_mercenary.py new file mode 100644 index 0000000..4e4926b --- /dev/null +++ b/assets-source/phase4/standalone/create_mercenary.py @@ -0,0 +1,3198 @@ +"""Saumwacht · Söldner · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 's01' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 's01', + 'name': 'Nadelspäher', + 'faction': 'neutral', + 'palette': 'neutral', + 'role': 'mercenary', + 'upgraded': False, + 'height': 1.4, + 'footprint': 1.85, + 'file': 'unit_s01.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 's02', + 'name': 'Rostschieber', + 'faction': 'neutral', + 'palette': 'neutral', + 'role': 'mercenary', + 'upgraded': False, + 'height': 1.4, + 'footprint': 1.85, + 'file': 'unit_s02.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 's03', + 'name': 'Dunstsänger', + 'faction': 'neutral', + 'palette': 'neutral', + 'role': 'mercenary', + 'upgraded': False, + 'height': 1.4, + 'footprint': 1.85, + 'file': 'unit_s03.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 's04', + 'name': 'Keilbrecher', + 'faction': 'neutral', + 'palette': 'neutral', + 'role': 'mercenary', + 'upgraded': False, + 'height': 1.4, + 'footprint': 1.85, + 'file': 'unit_s04.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 's05', + 'name': 'Risszehrer', + 'faction': 'neutral', + 'palette': 'neutral', + 'role': 'mercenary', + 'upgraded': False, + 'height': 1.5499999999999998, + 'footprint': 1.85, + 'file': 'unit_s05.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, pi, sin + + + +def _prism(name, outline, front_y, back_y, material): + """Extrude an X/Z outline along Y, useful for readable masks and wedges.""" + area = sum(outline[i][0] * outline[(i + 1) % len(outline)][1] + - outline[(i + 1) % len(outline)][0] * outline[i][1] + for i in range(len(outline))) + if area < 0: + outline = list(reversed(outline)) + count = len(outline) + vertices = [(x, front_y, z) for x, z in outline] + vertices += [(x, back_y, z) for x, z in outline] + faces = [tuple(range(count)), tuple(range(2 * count - 1, count - 1, -1))] + for i in range(count): + following = (i + 1) % count + faces.append((i, i + count, following + count, following)) + return mesh_object(name, vertices, faces, material) + + +def _figure(spec, nominal_height): + """Scaled primitive wrappers keep species proportions stable at any height.""" + scale = float(spec.get("height", nominal_height)) / nominal_height + + def point(value): + return tuple(component * scale for component in value) + + class Figure: + def box(self, name, loc, size, material, rotation=None): + return box(name, point(loc), point(size), material, rotation=rotation) + + def ellipsoid(self, name, loc, size, material, subdivisions=1): + return ellipsoid(name, point(loc), point(size), material, subdivisions=subdivisions) + + def cylinder(self, name, loc, radius, depth, material, vertices=8, rotation=None): + return cylinder(name, point(loc), radius * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def cone(self, name, loc, radius1, radius2, depth, material, vertices=8, rotation=None): + return cone(name, point(loc), radius1 * scale, radius2 * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def beam(self, name, start, end, radius, material, vertices=6): + return beam(name, point(start), point(end), radius * scale, + material, vertices=vertices) + + def ring(self, name, loc, major_radius, minor_radius, material, + rotation=None, segments=10): + return ring(name, point(loc), major_radius * scale, minor_radius * scale, + material, rotation=rotation, segments=segments) + + def prism(self, name, outline, front_y, back_y, material): + return _prism(name, [(x * scale, z * scale) for x, z in outline], + front_y * scale, back_y * scale, material) + + return Figure() + + +def _boots(f, material, x=0.22, width=0.26, height=0.18, depth=0.42): + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side + "_Boot", (sign * x, -0.075, height / 2), + (width, depth, height), material) + + +def _eyes(f, material, z, y, separation=0.10): + for side, sign in (("L", -1), ("R", 1)): + f.box("Head_Eye" + side, (sign * separation, y, z), + (0.065, 0.025, 0.034), material) + + +def build_lane(spec, mat): + """12 m traversable width, 4 m repeat length, deck at Z=0. + + Side decoration remains strictly outside X=[-6,+6], and nothing extends + past Y=[-2,+2], so consecutive copies meet without a transverse obstacle. + """ + box("Body_LaneFoundation", (0, 0, -0.195), (12, 4, 0.31), mat["primary"]) + for column in range(6): + box("Body_LaneSlab_%02d" % column, (-5 + column * 2, 0, -0.02), + (2, 4, 0.04), mat["primary"]) + for side, sign in (("L", -1), ("R", 1)): + box("Body_" + side + "RetainingLip", (sign * 6.15, 0, -0.10), + (0.30, 4, 0.50), mat["secondary"]) + for index, y in enumerate((-1.42, 0, 1.42)): + ellipsoid("Body_" + side + "Basalt_%02d" % index, + (sign * 6.46, y, -0.05), + (0.26, 0.42, 0.26 if index != 1 else 0.30), mat["secondary"]) + for index, y in enumerate((-1.15, 1.15)): + box("Body_" + side + "BrassMarker_%02d" % index, + (sign * 6.15, y, 0.165), (0.19, 0.20, 0.03), mat["accent"]) + ellipsoid("Body_" + side + "Moss", (sign * 6.39, 0.65, 0.02), + (0.17, 0.34, 0.13), mat["light"]) + empty("Anchor_Deck", (0, 0, 0)) + empty("Anchor_JoinNorth", (0, 2, 0)) + empty("Anchor_JoinSouth", (0, -2, 0)) + + +def build_core(spec, mat): + """A grounded crystal cradle with a physical team circle or triangle.""" + triangular = int(spec.get("team", 0)) == 1 + sides = 3 if triangular else 12 + cylinder("Body_CorePlinth", (0, 0, 0.13), 1.26, 0.26, + mat["primary"], vertices=sides) + cylinder("Body_BrassPlinthRim", (0, 0, 0.285), 1.18, 0.05, + mat["secondary"], vertices=sides) + cylinder("Body_CradleStep", (0, 0, 0.37), 0.85, 0.12, + mat["primary"], vertices=8) + if triangular: + points = [(1.06 * sin(i * 2 * pi / 3), -1.06 * cos(i * 2 * pi / 3), 0.34) + for i in range(3)] + for i in range(3): + beam("Team_Triangle_%d" % i, points[i], points[(i + 1) % 3], + 0.045, mat["accent"], vertices=6) + else: + ring("Team_Circle", (0, 0, 0.345), 1.025, 0.045, mat["accent"], segments=20) + # Multiple low-poly rings create a recognizable mineral, not a sphere. + vertices = [(0, 0, 0.51)] + for radius, z in ((0.37, 0.70), (0.58, 1.16), (0.36, 1.72)): + vertices.extend((radius * cos(i * pi / 3), radius * sin(i * pi / 3), z) + for i in range(6)) + vertices.append((0, 0, 2.20)) + faces = [(0, 1 + (i + 1) % 6, 1 + i) for i in range(6)] + for row in range(2): + start = 1 + 6 * row + for i in range(6): + following = (i + 1) % 6 + faces.append((start + i, start + following, + start + 6 + following, start + 6 + i)) + faces.extend((13 + i, 13 + (i + 1) % 6, 19) for i in range(6)) + mesh_object("Body_CoreCrystal", vertices, faces, mat["accent"]) + for index in range(4): + angle = pi / 4 + index * pi / 2 + x, y = sin(angle), cos(angle) + beam("Arm_Cradle_%d" % index, (x * 0.72, y * 0.72, 0.42), + (x * 0.47, y * 0.47, 0.88), 0.075, mat["secondary"]) + ellipsoid("Arm_CradleClasp_%d" % index, + (x * 0.48, y * 0.48, 0.85), (0.12, 0.12, 0.09), mat["light"]) + empty("Anchor_CoreEffect", (0, 0, 1.25)) + + +def build_worker(spec, mat): + """Small clay Funkenleser with a fork and a framed energy container.""" + f = _figure(spec, 1.1) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.14, depth=0.31) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.16, 0, 0.14), + (sign * 0.15, 0, 0.36), 0.10, mat["primary"]) + f.ellipsoid("Body_Clay", (0, 0, 0.49), (0.30, 0.21, 0.30), mat["primary"]) + f.prism("Body_Apron", [(-0.20, 0.68), (-0.24, 0.30), (0.24, 0.30), (0.20, 0.68)], + -0.23, -0.19, mat["secondary"]) + f.box("Body_Buckle", (0, -0.248, 0.56), (0.10, 0.035, 0.07), mat["accent"]) + f.ellipsoid("Head_Hood", (0, 0.005, 0.88), (0.26, 0.235, 0.22), mat["secondary"]) + f.ellipsoid("Head_ClayFace", (0, -0.175, 0.88), (0.195, 0.10, 0.17), mat["primary"]) + _eyes(f, mat["secondary"], 0.905, -0.274, separation=0.075) + f.beam("ArmL", (-0.23, 0, 0.64), (-0.40, -0.19, 0.52), 0.085, mat["primary"]) + f.beam("ArmR", (0.23, 0, 0.64), (0.39, -0.23, 0.54), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.40, -0.19, 0.52), (0.105, 0.09, 0.09), mat["primary"]) + f.ellipsoid("ArmR_Hand", (0.39, -0.23, 0.54), (0.105, 0.09, 0.09), mat["primary"]) + f.beam("Weapon_SparkForkHandle", (-0.43, -0.20, 0.13), (-0.43, -0.20, 0.78), + 0.032, mat["accent"]) + for sign in (-1, 1): + f.beam("Weapon_SparkForkProng_%d" % sign, (-0.43, -0.20, 0.78), + (-0.43 + sign * 0.10, -0.20, 0.99), 0.026, mat["accent"]) + f.cylinder("Weapon_ContainerBase", (0.44, -0.24, 0.32), 0.11, 0.045, mat["accent"]) + f.cylinder("Weapon_ContainerLid", (0.44, -0.24, 0.61), 0.11, 0.045, mat["accent"]) + # An open brass cage gives glass-like legibility without alpha sorting. + for index in range(4): + angle = index * pi / 2 + f.beam("Weapon_ContainerRib_%d" % index, + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.33), + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.60), + 0.016, mat["accent"], vertices=4) + f.ellipsoid("Weapon_CapturedSpark", (0.44, -0.24, 0.47), + (0.058, 0.058, 0.105), mat["light"]) + + +def _scout(spec, mat): + f = _figure(spec, 1.70) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.18) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.18, 0, 0.17), + (sign * 0.15, 0, 0.78), 0.087, mat["primary"]) + f.box("Leg" + side + "_ShinPlate", (sign * 0.18, -0.095, 0.35), + (0.13, 0.05, 0.24), mat["secondary"]) + f.cone("Body_Armor", (0, 0, 0.97), 0.22, 0.28, 0.49, mat["primary"], vertices=6) + f.box("Body_Belt", (0, 0, 0.77), (0.44, 0.30, 0.10), mat["secondary"]) + f.ellipsoid("Head_Hood", (0, 0.015, 1.42), (0.23, 0.21, 0.25), mat["primary"]) + f.cone("Head_HoodPoint", (0, 0.055, 1.60), 0.145, 0, 0.20, mat["primary"], vertices=5) + f.prism("Head_Mask", [(-0.15, 1.54), (-0.13, 1.32), (0, 1.26), (0.13, 1.32), (0.15, 1.54)], + -0.21, -0.165, mat["light"]) + _eyes(f, mat["primary"], 1.46, -0.225, separation=0.075) + f.beam("ArmL_Upper", (-0.24, 0, 1.12), (-0.34, -0.17, 0.96), 0.078, mat["primary"]) + f.beam("ArmL_Fore", (-0.34, -0.17, 0.96), (-0.06, -0.37, 1.02), 0.071, mat["primary"]) + f.beam("ArmR_Upper", (0.24, 0, 1.12), (0.35, -0.15, 0.97), 0.078, mat["primary"]) + f.beam("ArmR_Fore", (0.35, -0.15, 0.97), (0.25, -0.43, 1.07), 0.071, mat["primary"]) + f.box("Weapon_DartLauncherStock", (0.19, -0.34, 1.07), (0.19, 0.44, 0.15), mat["secondary"]) + f.cylinder("Weapon_DartLauncherBarrel", (0.19, -0.66, 1.09), + 0.065, 0.34, mat["light"], rotation=(pi / 2, 0, 0)) + f.cylinder("Weapon_DartLauncherBore", (0.19, -0.836, 1.09), + 0.04, 0.008, mat["primary"], rotation=(pi / 2, 0, 0)) + f.box("Body_DartQuiver", (-0.14, 0.23, 1.02), (0.23, 0.17, 0.45), mat["secondary"], + rotation=(0, -0.16, 0)) + for index in range(3): + x = -0.23 + index * 0.085 + f.beam("Weapon_SpareDart_%d" % index, (x, 0.24, 1.10), (x - 0.06, 0.24, 1.47), + 0.024, mat["light"], vertices=4) + + +def _ram(spec, mat): + f = _figure(spec, 1.48) + _boots(f, mat["primary"], x=0.27, width=0.35, height=0.20, depth=0.45) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.27, 0, 0.35), (0.25, 0.30, 0.35), mat["primary"]) + f.ellipsoid("Arm" + side + "_Pauldron", (sign * 0.43, 0, 1.05), + (0.27, 0.25, 0.25), mat["secondary"]) + f.box("Body_RustArmor", (0, 0, 0.83), (0.74, 0.48, 0.67), mat["secondary"]) + f.box("Body_UpperLamella", (0, -0.256, 1.01), (0.71, 0.06, 0.18), mat["primary"]) + f.box("Body_LowerLamella", (0, -0.261, 0.80), (0.71, 0.06, 0.16), mat["primary"]) + f.ellipsoid("Head_Helmet", (0, 0, 1.29), (0.27, 0.23, 0.19), mat["primary"]) + f.box("Head_BrowGuard", (0, -0.23, 1.35), (0.45, 0.085, 0.10), mat["light"]) + _eyes(f, mat["accent"], 1.275, -0.235) + f.beam("ArmL", (-0.43, 0, 1.03), (-0.43, -0.40, 0.81), 0.14, mat["primary"]) + f.beam("ArmR", (0.43, 0, 1.03), (0.61, -0.18, 0.72), 0.14, mat["primary"]) + f.box("ArmR_HammerFist", (0.61, -0.19, 0.66), (0.30, 0.28, 0.29), mat["secondary"]) + outline = [(-0.63, 1.09), (-0.68, 0.34), (-0.48, 0.21), (0.45, 0.21), + (0.65, 0.34), (0.60, 1.09)] + f.prism("Weapon_RamShield", outline, -0.54, -0.39, mat["secondary"]) + f.box("Weapon_ShieldTopRim", (-0.015, -0.575, 1.05), (1.18, 0.07, 0.095), mat["light"]) + f.prism("Weapon_CentralWedge", [(-0.13, 0.94), (-0.18, 0.37), (0, 0.28), (0.18, 0.37), (0.13, 0.94)], + -0.74, -0.53, mat["primary"]) + + +def _singer(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.12, depth=0.32) + f.cone("Body_BellRobe", (0, 0, 0.63), 0.43, 0.20, 1.10, mat["primary"], vertices=8) + for index, x in enumerate((-0.22, 0, 0.22)): + f.prism("Body_RobeFold_%d" % index, + [(x - 0.055, 0.15), (x + 0.055, 0.15), (x * 0.45, 1.09)], + -0.32, -0.24, mat["accent"]) + f.ellipsoid("Body_Mantle", (0, 0, 1.24), (0.37, 0.27, 0.21), mat["accent"]) + f.ellipsoid("Head_DeepHood", (0, 0, 1.57), (0.26, 0.25, 0.25), mat["primary"]) + f.prism("Head_SingerMask", [(-0.13, 1.68), (-0.12, 1.47), (0, 1.41), (0.12, 1.47), (0.13, 1.68)], + -0.246, -0.21, mat["light"]) + _eyes(f, mat["primary"], 1.60, -0.257, separation=0.065) + f.beam("ArmL", (-0.29, 0, 1.27), (-0.34, -0.37, 1.05), 0.085, mat["primary"]) + f.beam("ArmR", (0.29, 0, 1.27), (0.36, -0.43, 1.10), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.34, -0.37, 1.05), (0.095, 0.075, 0.075), mat["light"]) + f.ellipsoid("ArmR_Hand", (0.36, -0.43, 1.10), (0.095, 0.075, 0.075), mat["light"]) + f.beam("Weapon_HornPipe", (-0.30, -0.37, 1.08), (0.36, -0.43, 1.13), 0.075, mat["secondary"]) + # A true open bell: two rings connected by a tapered shell, no filled mouth. + vertices = [] + for y, radius in ((-0.43, 0.075), (-0.84, 0.28), (-0.81, 0.235), (-0.47, 0.042)): + for index in range(10): + angle = index * pi / 5 + vertices.append((0.36 + cos(angle) * radius, y, 1.13 + sin(angle) * radius)) + faces = [] + for row in range(3): + for i in range(10): + j = (i + 1) % 10 + faces.append((row * 10 + i, row * 10 + j, (row + 1) * 10 + j, (row + 1) * 10 + i)) + scale = float(spec.get("height", 1.82)) / 1.82 + mesh_object("Weapon_ResonanceHorn", [tuple(v * scale for v in point) for point in vertices], + faces, mat["secondary"]) + f.ring("Weapon_HornRim", (0.36, -0.84, 1.13), 0.258, 0.023, mat["light"], + rotation=(pi / 2, 0, 0)) + + +def _breaker(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.28, width=0.36, height=0.22, depth=0.49) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.26, 0, 0.47), (0.28, 0.31, 0.54), mat["primary"]) + f.box("Leg" + side + "_Knee", (sign * 0.27, -0.19, 0.51), + (0.27, 0.13, 0.24), mat["secondary"]) + f.box("Arm" + side + "_Pauldron", (sign * 0.48, 0, 1.29), + (0.42, 0.52, 0.34), mat["primary"], rotation=(0, sign * 0.14, 0)) + f.cone("Body_SteelTorso", (0, 0, 1.01), 0.35, 0.47, 0.70, mat["primary"], vertices=6) + f.prism("Body_RustChestInset", [(-0.28, 1.29), (0, 0.95), (0.28, 1.29)], + -0.397, -0.35, mat["secondary"]) + f.box("Head_Helmet", (0, 0, 1.61), (0.43, 0.40, 0.42), mat["primary"]) + f.prism("Head_Faceplate", [(-0.17, 1.76), (-0.17, 1.50), (0, 1.44), (0.17, 1.50), (0.17, 1.76)], + -0.23, -0.19, mat["light"]) + f.box("Head_Visor", (0, -0.246, 1.66), (0.25, 0.026, 0.045), mat["primary"]) + f.beam("ArmL", (-0.47, 0, 1.25), (-0.31, -0.50, 0.92), 0.12, mat["primary"]) + f.beam("ArmR", (0.47, 0, 1.25), (0.30, -0.50, 1.20), 0.12, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.31, -0.50, 0.92), (0.145, 0.12, 0.12), mat["secondary"]) + f.ellipsoid("ArmR_Hand", (0.30, -0.50, 1.20), (0.145, 0.12, 0.12), mat["secondary"]) + f.beam("Weapon_HammerShaft", (-0.65, -0.51, 0.77), (0.66, -0.51, 1.36), + 0.055, mat["secondary"]) + f.prism("Weapon_KeilhammerHead", [(0.40, 1.26), (0.43, 1.58), (0.82, 1.80), + (1.02, 1.61), (0.90, 1.18)], + -0.79, -0.24, mat["primary"]) + # Offset along the sloped edge normal; coplanar cap faces would flicker. + f.prism("Weapon_ChiselEdge", [(0.832, 1.814), (1.032, 1.624), (0.992, 1.354), (0.932, 1.644)], + -0.80, -0.23, mat["light"]) + + +def _rift(spec, mat): + f = _figure(spec, 2.08) + _boots(f, mat["primary"], x=0.22, width=0.21, height=0.12, depth=0.35) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side + "_Shin", (sign * 0.22, 0, 0.12), + (sign * 0.30, 0.12, 0.45), 0.069, mat["primary"]) + f.beam("Leg" + side + "_Thigh", (sign * 0.30, 0.12, 0.45), + (sign * 0.17, 0, 0.81), 0.083, mat["primary"]) + f.ellipsoid("Body_Pelvis", (0, 0, 0.83), (0.25, 0.16, 0.16), mat["primary"]) + # Separate ribs bound real negative space; there is deliberately no chest fill. + for side, sign in (("L", -1), ("R", 1)): + f.beam("Body_" + side + "LowerRib", (sign * 0.15, 0, 0.89), + (sign * 0.31, 0, 1.18), 0.095, mat["primary"]) + f.beam("Body_" + side + "UpperRib", (sign * 0.31, 0, 1.18), + (sign * 0.21, 0, 1.52), 0.10, mat["primary"]) + f.beam("Body_" + side + "RiftSeam", (sign * 0.17, -0.080, 0.95), + (sign * 0.245, -0.080, 1.18), 0.019, mat["accent"], vertices=4) + f.beam("Body_" + side + "RiftUpperSeam", (sign * 0.245, -0.080, 1.18), + (sign * 0.16, -0.080, 1.46), 0.019, mat["accent"], vertices=4) + f.beam("Body_Collar", (-0.21, 0, 1.52), (0.21, 0, 1.52), 0.095, mat["primary"]) + f.ellipsoid("Head_HollowShell", (0, 0, 1.73), (0.20, 0.155, 0.23), mat["primary"]) + f.box("Head_RiftMouth", (0, -0.153, 1.69), (0.17, 0.025, 0.043), mat["accent"]) + for index, (x, z) in enumerate(((-0.19, 1.90), (-0.10, 2.02), (0.10, 2.02), (0.19, 1.90))): + f.beam("Head_BrokenCrown_%d" % index, (x, 0, z - 0.13), (x * 1.18, 0, z + 0.06), + 0.038, mat["light"], vertices=5) + f.beam("ArmL_Upper", (-0.30, 0, 1.47), (-0.48, 0.02, 1.13), 0.068, mat["primary"]) + f.beam("ArmL_Fore", (-0.48, 0.02, 1.13), (-0.46, -0.18, 0.77), 0.056, mat["primary"]) + for index in range(3): + f.beam("ArmL_Claw_%d" % index, (-0.50 + index * 0.043, -0.18, 0.79), + (-0.51 + index * 0.049, -0.25, 0.64), 0.020, mat["light"], vertices=4) + f.beam("ArmR_Upper", (0.30, 0, 1.47), (0.49, 0, 1.10), 0.068, mat["primary"]) + f.beam("ArmR_Fore", (0.49, 0, 1.10), (0.37, -0.33, 1.23), 0.056, mat["primary"]) + f.ellipsoid("ArmR_CradlingHand", (0.37, -0.33, 1.23), (0.12, 0.09, 0.052), mat["primary"]) + f.ellipsoid("Weapon_DrainOrb", (0.37, -0.34, 1.40), (0.13, 0.13, 0.13), mat["accent"]) + f.ring("Weapon_DrainOrbit", (0.37, -0.34, 1.40), 0.175, 0.015, + mat["light"], rotation=(0.35, 0.20, 0), segments=10) + + +def build_mercenary(spec, mat): + """Dispatch five neutral mercenaries, retaining recognizable role silhouettes.""" + builders = {"s01": _scout, "s02": _ram, "s03": _singer, + "s04": _breaker, "s05": _rift} + identifier = str(spec["id"]) + if identifier not in builders: + raise ValueError("Unknown Saumwacht mercenary: " + identifier) + builders[identifier](spec, mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_ranged.py b/assets-source/phase4/standalone/create_ranged.py new file mode 100644 index 0000000..58236fe --- /dev/null +++ b/assets-source/phase4/standalone/create_ranged.py @@ -0,0 +1,3440 @@ +"""Saumwacht · Fernkämpfer · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'g05' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'g05', + 'name': 'Funkenlanze', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'ranged', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_g05.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'g06', + 'name': 'Glasballiste', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'ranged', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_g06.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'm05', + 'name': 'Bolzenknecht', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'ranged', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_m05.glb'}, + {'id': 'm06', + 'name': 'Linienmeister', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'ranged', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_m06.glb'}, + {'id': 'n05', + 'name': 'Fernflüsterer', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'ranged', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_n05.glb'}, + {'id': 'n06', + 'name': 'Fernrufer', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'ranged', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_n06.glb'}, + {'id': 'w05', + 'name': 'Samenschleuder', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'ranged', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_w05.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'w06', + 'name': 'Zapfenkrone', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'ranged', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_w06.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, sin, pi, sqrt + + + +def _add(a, b): + return tuple(a[i] + b[i] for i in range(3)) + + +def _mul(a, scale): + return tuple(v * scale for v in a) + + +def _cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def _unit(a): + length = sqrt(sum(v * v for v in a)) + return tuple(v / length for v in a) + + +def _frame(axis): + w = _unit(axis) + reference = (0, 0, 1) if abs(w[2]) < .9 else (0, 1, 0) + u = _unit(_cross(reference, w)) + return u, _cross(w, u), w + + +def _lathe(name, loc, profile, mat, axis=(0, 0, 1), segments=10): + """Closed profile, including real inner walls; zero radii become poles. + + Profile travels from the back/bottom up the outside, down the inside. + Independent pole vertices avoid degenerate zero-area triangles. + """ + u, v, w = _frame(axis) + verts, loops, faces = [], [], [] + for radius, depth in profile: + if radius == 0: + loops.append([len(verts)]) + verts.append(_add(loc, _mul(w, depth))) + continue + loop = [] + for k in range(segments): + angle = 2 * pi * k / segments + offset = _add(_mul(w, depth), + _add(_mul(u, radius * cos(angle)), + _mul(v, radius * sin(angle)))) + loop.append(len(verts)) + verts.append(_add(loc, offset)) + loops.append(loop) + for j in range(len(loops)): + low, high = loops[j], loops[(j + 1) % len(loops)] + if len(low) == 1 and len(high) == 1: + continue + for k in range(segments): + nxt = (k + 1) % segments + if len(low) == 1: + faces.append((low[0], high[nxt], high[k])) + elif len(high) == 1: + faces.append((low[k], low[nxt], high[0])) + else: + faces.append((low[k], low[nxt], high[nxt], high[k])) + mesh_object(name, verts, faces, mat) + + +def _cup(name, loc, radius, depth, mat, axis=(0, 0, 1), segments=10): + # The rim is 13% thick; the inset bottom is visible from above/front. + _lathe(name, loc, [(0, 0), (radius * .5, .04), + (radius * .73, depth * .35), (radius, depth), + (radius * .87, depth), (radius * .59, depth * .35), + (0, depth * .20)], mat, axis, segments) + + +def _horn(name, loc, radius, depth, mat, axis=(0, -1, .18)): + _lathe(name, loc, [(radius * .16, 0), (radius * .25, depth * .42), + (radius * .58, depth * .76), (radius, depth), + (radius * .84, depth), (radius * .43, depth * .72), + (radius * .1, depth * .35), (0, depth * .29), + (0, 0)], mat, axis, 10) + + +def _spike(name, start, end, radius, mat, sides=5): + axis = tuple(end[i] - start[i] for i in range(3)) + u, v, _ = _frame(axis) + verts = [_add(start, _add(_mul(u, radius * cos(2 * pi * k / sides)), + _mul(v, radius * sin(2 * pi * k / sides)))) + for k in range(sides)] + verts.append(end) + faces = [tuple(reversed(range(sides)))] + faces.extend((k, (k + 1) % sides, sides) for k in range(sides)) + mesh_object(name, verts, faces, mat) + + +def _leaf(name, loc, width, height, mat, lean=0): + # Thick diamond leaf: large central ridge, only eight triangles. + x, y, z = loc + verts = [(x, y, z), (x - width / 2, y, z + height * .42), + (x + lean, y + .05, z + height), + (x + width / 2, y, z + height * .42), + (x + lean * .3, y - .09, z + height * .45), + (x + lean * .3, y + .055, z + height * .45)] + faces = [(0, 4, 1), (1, 4, 2), (2, 4, 3), (3, 4, 0), + (1, 5, 0), (2, 5, 1), (3, 5, 2), (0, 5, 3)] + mesh_object(name, verts, faces, mat) + + +def _eyes(loc, mat, spread=.075, scale=.038): + for side, suffix in ((-1, "L"), (1, "R")): + p = (loc[0] + side * spread, loc[1], loc[2]) + ellipsoid("Head_Eye" + suffix, p, (scale, .023, scale * .75), mat) + + +def _mask(name, loc, scale, mat, eyes_mat): + ellipsoid(name, loc, (.15 * scale, .075 * scale, .22 * scale), mat) + for sign, suffix in ((-1, "L"), (1, "R")): + ellipsoid(name + "_Eye" + suffix, + (loc[0] + sign * .052 * scale, loc[1] - .071 * scale, + loc[2] + .023 * scale), + (.028 * scale, .012 * scale, .046 * scale), eyes_mat) + + +def _basalt_legs(mat, wide=False): + spread = .32 if wide else .22 + for side, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Leg" + suffix + "_Foot", (side * spread, -.075, .12), + (.20 if wide else .15, .24, .12), mat) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .15), + (side * spread * .7, .02, .49), .095, mat, vertices=6) + + +def _mechanical_legs(mat, wide=False): + spread = .27 if wide else .20 + for side, suffix in ((-1, "L"), (1, "R")): + box("Leg" + suffix + "_Foot", (side * spread, -.07, .07), + (.22, .33, .14), mat["accent"]) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .14), + (side * spread, .08, .35), .065, mat["accent"], vertices=6) + ellipsoid("Leg" + suffix + "_Knee", (side * spread, .08, .35), + (.10, .10, .10), mat["secondary"]) + beam("Leg" + suffix + "_Thigh", (side * spread, .08, .35), + (side * spread * .66, 0, .57), .09, mat["primary"], vertices=6) + + +def _root_feet(mat, count=4, spread=.43, top=.60): + for k in range(count): + a = 2 * pi * k / count + pi / 4 + base = (spread * cos(a), spread * sin(a), .055) + elbow = (spread * .6 * cos(a), spread * .6 * sin(a), .24) + suffix = str(k + 1) + beam("Leg_Root" + suffix, base, elbow, .09, mat, vertices=5) + beam("Leg_RootUpper" + suffix, elbow, (0, .02, top), .12, + mat, vertices=5) + ellipsoid("Leg_RootToe" + suffix, base, (.16, .10, .055), mat) + + +def _mist_robe(mat, upgraded=False): + # Alternating long cloth points touch the floor; the upper body floats. + cone("Body_Robe", (0, .035, .49), .31 if upgraded else .25, + .13, .74, mat["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + _spike("Body_ClothPoint" + str(k), + (.16 * cos(a), .035 + .16 * sin(a), .35), + (.31 * cos(a), .035 + .27 * sin(a), .015), .11, + mat["secondary"] if k % 2 else mat["primary"]) + ellipsoid("Body_Chest", (0, 0, .90), (.23, .16, .23), mat["secondary"]) + + +def _glut_ranged(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_Core", (0, .035, .69), (.30 if up else .21, .22, .27), + m["primary"]) + ellipsoid("Head_Helm", (0, -.015, 1.12), (.19, .16, .20), m["light"]) + _eyes((0, -.17, 1.13), m["secondary"]) + box("Body_Ember", (0, -.197, .71), (.11, .045, .19), m["secondary"]) + if up: + # Broad glass bow arms distinguish the upgrade from the slender lance. + box("Weapon_Rail", (0, -.20, .96), (.10, .98, .09), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .2, 0, .88), (s * .30, -.15, .91), + .075, m["primary"], vertices=6) + _spike("Weapon_GlassBow" + suffix, (s * .06, -.25, .99), + (s * .62, -.04, 1.25), .16, m["secondary"]) + beam("Weapon_String" + suffix, (s * .62, -.04, 1.25), + (0, .22, 1.03), .012, m["light"], vertices=4) + beam("Weapon_Bolt", (0, .20, 1.02), (0, -.64, 1.02), .025, m["light"]) + _spike("Weapon_BoltHead", (0, -.57, 1.02), (0, -.80, 1.02), + .08, m["secondary"]) + else: + beam("ArmL", (-.15, 0, .89), (-.25, -.07, .70), .07, m["primary"]) + beam("ArmR", (.15, 0, .90), (.30, -.19, .91), .075, m["primary"]) + beam("Weapon_Lance", (.29, .34, .81), (.29, -.60, 1.05), .038, + m["accent"]) + _spike("Weapon_GlassTip", (.29, -.53, 1.03), (.29, -.81, 1.11), + .105, m["secondary"]) + + +def _nieten_ranged(up, m): + _mechanical_legs(m) + cone("Body_Cuirass", (0, .02, .78), .21, .27, .43, m["primary"], vertices=6) + box("Body_Plate", (0, -.18, .80), (.27, .09, .22), m["secondary"]) + beam("Head_Neck", (0, 0, 1.0), (0, 0, 1.10), .075, m["accent"]) + box("Head_Housing", (0, -.015, 1.22), (.29, .25, .25), m["light"]) + box("Head_Visor", (0, -.146, 1.23), (.18, .028, .05), m["primary"]) + weapon_x = 0 if up else .29 + beam("ArmL", (-.21, 0, .92), (-.28, -.13, .77), .065, m["accent"]) + beam("ArmR", (.21, 0, .92), (weapon_x + .07, -.24, .91), .065, + m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Weapon_Rail" + suffix, (weapon_x + s * .055, -.30, .97), + (.055, .82 if up else .61, .07), m["accent"]) + tip = (weapon_x + s * (.44 if up else .23), -.27, .97) + beam("Weapon_Bow" + suffix, (weapon_x, -.43, .97), tip, .055, + m["secondary"], vertices=6) + beam("Weapon_String" + suffix, tip, (weapon_x, .02, .97), .011, + m["light"], vertices=4) + _spike("Weapon_Bolt", (weapon_x, -.44, .98), + (weapon_x, -.78 if up else -.66, .98), .052, m["light"]) + if up: + box("Weapon_Sight", (0, -.13, 1.08), (.08, .25, .09), m["primary"]) + _spike("Head_Crest", (0, .03, 1.34), (0, .10, 1.58), .075, + m["secondary"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Arm" + suffix + "_Pauldron", (s * .27, .01, .96), + (.16, .25, .13), m["secondary"]) + + +def _nebel_ranged(up, m): + _mist_robe(m, up) + _mask("Head_Mask", (0, -.105, 1.18), 1.0, m["light"], m["primary"]) + _leaf("Head_Hood", (0, .055, 1.16), .35, .37, m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, 0, .94), (s * .31, -.18, .77), + .055, m["secondary"], vertices=5) + horn_sides = (-1, 1) if up else (1,) + for s in horn_sides: + suffix = "L" if s < 0 else "R" + root = (s * .25, -.12, .79) + elbow = (s * .46, .07, 1.08 if up else .97) + mouth = (s * (.48 if up else .31), -.03, 1.27 if up else 1.02) + beam("Weapon_HornStem" + suffix, root, elbow, .055, m["secondary"]) + beam("Weapon_HornCurve" + suffix, elbow, mouth, .072, m["light"]) + _horn("Weapon_HornBell" + suffix, mouth, .19 if up else .16, + .40 if up else .49, m["light"]) + axis = _unit((0, -1, .18)) + lip = _add(mouth, _mul(axis, .39 if up else .48)) + _lathe("Weapon_MintLip" + suffix, lip, + [(.19 if up else .16, 0), (.19 if up else .16, .025), + (.16 if up else .132, .025), (.16 if up else .132, 0)], + m["accent"], axis) + + +def _wurzel_ranged(up, m): + _root_feet(m["primary"], 3, .34, .56) + ellipsoid("Body_Trunk", (0, .025, .76), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.025, 1.13), (.17, .15, .20), m["secondary"]) + _eyes((0, -.17, 1.13), m["accent"], spread=.057, scale=.03) + _leaf("Body_LeafMantle", (0, -.14, .59), .43, .40, m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + shoulder = (s * .17, 0, .91) + hand = (s * .29, -.21, .85) + beam("Arm" + suffix, shoulder, hand, .07, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .26, -.13, .81), .21, .26, + m["secondary"], lean=s * .1) + beam("Weapon_VineLower", (.28, -.17, .73), (.44, -.08, .93), .046, + m["primary"], vertices=5) + beam("Weapon_VineUpper", (.44, -.08, .93), (.40, -.17, 1.17), .04, + m["primary"], vertices=5) + _cup("Weapon_SeedCapsule", (.24, -.19, .88), .19 if up else .15, + .20, m["accent"], axis=(0, -.7, .7), segments=8) + ellipsoid("Weapon_Seed", (.24, -.30, 1.02), (.075, .075, .10), m["light"]) + if up: + # Overlapping tiers make a pinecone crown, not a mushroom cap. + for layer in range(3): + z = 1.24 + layer * .10 + radius = .23 - layer * .035 + cone("Head_ConeTier" + str(layer), (0, .025, z), radius, + radius * .47, .16, m["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + layer * .3 + _leaf("Head_ConeScale" + str(layer) + "_" + str(k), + (radius * .75 * cos(a), .025 + radius * .75 * sin(a), z - .05), + .11, .16, m["accent"]) + else: + _leaf("Head_LeafCrest", (0, .04, 1.22), .22, .25, m["accent"], .08) + + +def _glut_artillery(up, m): + _basalt_legs(m["primary"], True) + ellipsoid("Body_Foundation", (0, .025, .48), (.39, .31, .22), m["primary"]) + _cup("Weapon_Crater", (0, .02, .52), .55 if up else .43, + .63 if up else .50, m["primary"], segments=12) + _cup("Weapon_EmberLining", (0, .02, .66), .37 if up else .29, + .24 if up else .20, m["secondary"], segments=10) + for s, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Arm" + suffix + "_Slab", (s * .39, .0, .65), + (.13, .19, .25), m["primary"]) + ellipsoid("Head_Eye" + suffix, (s * .13, -.28, .53), + (.055, .025, .035), m["secondary"]) + for k in range(3 if up else 2): + ellipsoid("Weapon_Coal" + str(k), + ((k - (1 if up else .5)) * .12, .015, .80 if up else .77), + (.105, .10, .10), m["accent"]) + if up: + for k in range(5): + a = .2 + pi * k / 4 + _spike("Body_CraterFin" + str(k), + (.40 * cos(a), .03 + .39 * sin(a), .87), + (.46 * cos(a), .03 + .43 * sin(a), 1.37), .095, + m["primary"]) + + +def _nieten_artillery(up, m): + _mechanical_legs(m, True) + box("Body_Chassis", (0, .035, .67), (.56 if up else .45, .37, .34), + m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Piston", (s * .25, .1, .60), + (s * .34, .17, .96), .065, m["accent"]) + cylinder("Arm" + suffix + "_Collar", (s * .31, .15, .84), .095, + .15, m["secondary"], vertices=8) + bell_positions = (-.29, .29) if up else (0,) + for i, x in enumerate(bell_positions): + base = (x, .08, .92) + _horn("Weapon_Resonator" + str(i), base, .27 if up else .34, + .48, m["secondary"], axis=(0, -1, .3)) + # A dark interior cavity and a slim central piston remain visible. + beam("Weapon_Clapper" + str(i), (x, .045, .94), (x, -.26, 1.035), + .038, m["accent"]) + ellipsoid("Weapon_ClapperHead" + str(i), (x, -.27, 1.04), + (.09, .07, .09), m["light"]) + box("Head_Visor", (0, -.164, .68), (.20, .03, .075), m["light"]) + for x, suffix in ((-.24, "L"), (.24, "R")): + cylinder("Body_Exhaust" + suffix, (x, .25, 1.03), .075, + .50 if up else .34, m["accent"], vertices=8) + if up: + box("Body_Brow", (0, -.10, 1.34), (.66, .14, .085), m["primary"]) + cone("Head_Metronome", (0, -.03, 1.47), .10, 0, .20, + m["light"], vertices=4) + + +def _nebel_artillery(up, m): + # Face forward/slightly up: the cavity remains visible to an elevated camera. + _mist_robe(m, up) + bell_base = (0, -.16, 1.05 if up else .85) + radius, depth = (.45, .60) if up else (.38, .50) + _horn("Body_CathedralBell", bell_base, radius, depth, + m["light"], axis=(0, -1, .12)) + beam("Weapon_ClapperStem", (0, -.27, 1.09 if up else .90), + (0, -.70 if up else -.60, 1.0 if up else .80), .045, m["accent"]) + ellipsoid("Weapon_Clapper", (0, -.73 if up else -.63, 1.0 if up else .80), + (.13, .10, .13), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, .02, .96), + (s * .44, -.08, .63), .07, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .44, -.08, .63), + (s * .49, -.19, .94), .10, m["primary"]) + _mask("Head_Mask", (0, .035, 1.49 if up else 1.38), .65, + m["secondary"], m["accent"]) + if up: + for i, x in enumerate((-.27, 0, .27)): + beam("Head_SpireBase" + str(i), (x * .65, .08, 1.16), + (x, .09, 1.42), .075, m["primary"], vertices=5) + _spike("Head_Spire" + str(i), (x, .09, 1.40), + (x * .65, -.01, 1.71 if i == 1 else 1.59), + .075, m["light"]) + + +def _mushroom(name, loc, radius, height, m): + x, y, z = loc + cone(name + "_Stem", (x, y, z + height * .45), .095, .07, height * .9, + m["primary"], vertices=7) + # An angular overhanging cap and light gill ring form a readable roof. + cone(name + "_Gills", (x, y, z + height * .86), radius * .91, + radius * .5, .10, m["accent"], vertices=10) + cone(name + "_Cap", (x, y, z + height), radius, radius * .15, + .22, m["light"], vertices=10) + + +def _wurzel_artillery(up, m): + _root_feet(m["primary"], 5, .50 if up else .43, .56) + ellipsoid("Body_Moss", (0, .02, .48), (.32, .26, .18), m["secondary"]) + _cup("Weapon_SporeChalice", (0, -.10, .50), .40 if up else .43, + .43, m["light"], segments=12) + _cup("Weapon_SporeInterior", (0, -.10, .60), .28, .18, + m["secondary"], segments=10) + for i, x in enumerate((-.105, .105)): + ellipsoid("Weapon_Spore" + str(i), (x, -.08, .81), + (.06, .06, .075), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + _leaf("Arm" + suffix + "_Leaf", (s * .30, -.05, .46), .20, .36, + m["accent"], lean=s * .14) + if up: + _mushroom("Body_RoofL", (-.34, .12, .47), .30, .67, m) + _mushroom("Body_RoofR", (.34, .18, .47), .29, .81, m) + _mushroom("Body_RoofCrown", (0, .33, .54), .39, .98, m) + for x, suffix in ((-.12, "L"), (.12, "R")): + beam("Body_Buttress" + suffix, (x * 3, .33, .12), + (x, .31, 1.21), .075, m["primary"], vertices=5) + + +def _glut_support(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_FurnaceBack", (0, .11, .79), + (.34 if up else .28, .20, .37), m["primary"]) + _cup("Body_OpenHearth", (0, .015, .85), .28 if up else .23, + .33, m["accent"], axis=(0, -1, 0), segments=8) + ellipsoid("Body_Ember", (0, -.10, .85), (.12, .085, .15), m["secondary"]) + ellipsoid("Head_Capstone", (0, .01, 1.17), (.21, .17, .15), m["light"]) + _eyes((0, -.15, 1.16), m["secondary"], spread=.075) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .26, .01, .92), + (s * .33, -.33, .63), .09, m["primary"], vertices=6) + _cup("Weapon_WarmingBowl", (0, -.38, .52), .36 if up else .29, + .22, m["accent"], segments=10) + ellipsoid("Weapon_WarmCoal", (0, -.38, .61), (.15, .12, .07), + m["secondary"]) + if up: + # Upper-half sun rays stay behind the face, safely within the footprint. + for k in range(7): + a = pi * k / 6 + start = (.30 * cos(a), .09, 1.12 + .30 * sin(a)) + end = (.48 * cos(a), .11, 1.12 + .48 * sin(a)) + _spike("Head_SunRay" + str(k), start, end, .065, m["accent"]) + cone("Head_Crown", (0, .0, 1.34), .16, .23, .12, + m["accent"], vertices=8) + + +def _nieten_support(up, m): + _mechanical_legs(m, up) + cone("Body_Coat", (0, .02, .73), .37 if up else .24, + .20, .51, m["primary"], vertices=6) + box("Body_PendulumCase", (0, -.18, .79), (.18, .10, .30), m["secondary"]) + beam("Body_Pendulum", (0, -.24, .89), (.045, -.24, .64), .018, m["accent"]) + ellipsoid("Body_PendulumWeight", (.045, -.24, .65), (.07, .035, .07), + m["light"]) + ellipsoid("Head_Casing", (0, .015, 1.14), (.17, .14, .17), m["accent"]) + ellipsoid("Head_Dial", (0, -.119, 1.14), (.135, .025, .135), m["light"]) + beam("Head_DialHand", (0, -.15, 1.14), (.055, -.15, 1.22), .015, + m["primary"], vertices=4) + for s, suffix in ((-1, "L"), (1, "R")): + elbow = (s * .35, .0, .91) + hand = (s * .45, -.13, 1.10 if s > 0 else .89) + beam("Arm" + suffix + "_Upper", (s * .2, .02, .95), elbow, .06, + m["accent"]) + beam("Arm" + suffix + "_Fore", elbow, hand, .047, m["secondary"]) + ellipsoid("Arm" + suffix + "_Hand", hand, (.065, .065, .065), m["light"]) + beam("Weapon_Baton", (.45, -.13, 1.06), (.61, -.22, 1.45), .019, + m["light"], vertices=5) + if up: + for k, x in enumerate((-.18, 0, .18)): + _spike("Head_CrownTine" + str(k), (x, .015, 1.28), + (x, .015, 1.56 if k == 1 else 1.47), .06, + m["secondary"]) + box("Head_MetronomeBridge", (0, .015, 1.36), (.45, .12, .07), + m["secondary"]) + for s in (-1, 1): + _leaf("Body_CoatTail" + str(s), (s * .20, .20, .33), .24, .59, + m["secondary"], lean=s * .16) + else: + _spike("Head_Spindle", (0, .015, 1.28), (0, .015, 1.45), .055, + m["secondary"]) + + +def _nebel_support(up, m): + _mist_robe(m, up) + _mask("Head_MainMask", (0, -.13, 1.17), 1.0, m["light"], m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Lower", (s * .17, 0, .88), + (s * .37, -.04, .82), .062, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .37, -.04, .82), + (s * .49, -.04, 1.21), .095, m["primary"]) + _leaf("Body_SickleCollar" + suffix, (s * .13, .02, .88), .29, + .43 if up else .29, m["secondary"], lean=s * .29) + if up: + positions = ((-.51, -.035, 1.46), (0, .11, 1.65), (.51, -.035, 1.46)) + for i, p in enumerate(positions): + _mask("Head_CompanionMask" + str(i), p, .67, + m["light"], m["primary"]) + for i, x in enumerate((-.12, 0, .12)): + _spike("Head_Crown" + str(i), (x, -.035, 1.31), + (x * 1.2, -.035, 1.53 if i == 1 else 1.45), .045, + m["accent"]) + else: + _mask("Head_CompanionMask0", (.49, -.035, 1.44), .70, + m["light"], m["primary"]) + ellipsoid("Body_ChoirGem", (0, -.19, .83), (.055, .035, .09), m["accent"]) + + +def _flower(name, loc, scale, m): + for k in range(5): + a = 2 * pi * k / 5 + ellipsoid(name + "_Petal" + str(k), + (loc[0] + cos(a) * .09 * scale, + loc[1] + sin(a) * .09 * scale, loc[2]), + (.085 * scale, .07 * scale, .035 * scale), m["light"]) + ellipsoid(name + "_Heart", (loc[0], loc[1], loc[2] + .025 * scale), + (.052 * scale, .052 * scale, .035 * scale), m["accent"]) + + +def _wurzel_support(up, m): + _root_feet(m["primary"], 5 if up else 3, .45 if up else .31, .55) + # Two counter-leaning stems create an open woven body in the upgrade. + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_WovenRoot" + suffix, (s * .20, .02, .38), + (-s * .17, .015, .83), .105, m["primary"], vertices=5) + beam("Body_WovenRootTop" + suffix, (-s * .17, .015, .83), + (s * .11, .025, 1.16), .085, m["primary"], vertices=5) + else: + ellipsoid("Body_Trunk", (0, .025, .72), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.03, 1.12), (.15, .14, .18), m["secondary"]) + _eyes((0, -.17, 1.12), m["accent"], spread=.05, scale=.026) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .15, 0, .94), + (s * .28, -.27, .69), .065, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .23, -.21, .68), .21, .28, + m["secondary"], lean=s * .12) + _cup("Weapon_LeafBasin", (0, -.31, .62), .30 if up else .23, + .20, m["accent"], segments=8) + # Water uses the optional shared mint accent, with a leaf-colour fallback. + # Opaque faceted geometry avoids sorting issues until the VFX integration. + water = m.get("water", m["accent"]) + cylinder("Weapon_Pool", (0, -.31, .739), .21 if up else .145, + .025, water, vertices=10) + ellipsoid("Weapon_Dew", (0, -.31, .86), (.085, .075, .13), water) + _spike("Weapon_DewTip", (0, -.31, .93), (0, -.31, 1.035), .059, water) + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_CanopyStem" + suffix, (s * .17, .11, .88), + (s * .36, .14, 1.28), .055, m["primary"], vertices=5) + _leaf("Head_Canopy" + suffix, (s * .12, .10, 1.17), .56, .36, + m["secondary"], lean=s * .28) + _flower("Head_Flower" + suffix, (s * .31, .12, 1.43), 1.0, m) + _flower("Head_FlowerCrown", (0, .07, 1.53), .9, m) + else: + _leaf("Head_LeafCap", (0, .02, 1.23), .33, .25, m["accent"], -.06) + + +_RANGED = {"glutpakt": _glut_ranged, "nietenkonvent": _nieten_ranged, + "nebelchor": _nebel_ranged, "wurzelbund": _wurzel_ranged} +_ARTILLERY = {"glutpakt": _glut_artillery, "nietenkonvent": _nieten_artillery, + "nebelchor": _nebel_artillery, "wurzelbund": _wurzel_artillery} +_SUPPORT = {"glutpakt": _glut_support, "nietenkonvent": _nieten_support, + "nebelchor": _nebel_support, "wurzelbund": _wurzel_support} + + +def build_ranged(spec, mat): + """Build IDs *05 (base) and *06 (upgraded).""" + _RANGED[spec["faction"]](spec["upgraded"], mat) + + +def build_artillery(spec, mat): + """Build IDs *07 (base) and *08 (upgraded).""" + _ARTILLERY[spec["faction"]](spec["upgraded"], mat) + + +def build_support(spec, mat): + """Build IDs *09 (base) and *10 (upgraded).""" + _SUPPORT[spec["faction"]](spec["upgraded"], mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_support.py b/assets-source/phase4/standalone/create_support.py new file mode 100644 index 0000000..01994e2 --- /dev/null +++ b/assets-source/phase4/standalone/create_support.py @@ -0,0 +1,3440 @@ +"""Saumwacht · Unterstützer · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'g09' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'g09', + 'name': 'Herdhüter', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'support', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_g09.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'g10', + 'name': 'Sonnenesse', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'support', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_g10.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'm09', + 'name': 'Taktspindel', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'support', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_m09.glb'}, + {'id': 'm10', + 'name': 'Taktprälat', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'support', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_m10.glb'}, + {'id': 'n09', + 'name': 'Maskenkantor', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'support', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_n09.glb'}, + {'id': 'n10', + 'name': 'Vielstimmenkantor', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'support', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_n10.glb'}, + {'id': 'w09', + 'name': 'Tauhüter', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'support', + 'upgraded': False, + 'height': 1.45, + 'footprint': 1.85, + 'file': 'unit_w09.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'w10', + 'name': 'Quellgeflecht', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'support', + 'upgraded': True, + 'height': 1.5999999999999999, + 'footprint': 1.85, + 'file': 'unit_w10.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, sin, pi, sqrt + + + +def _add(a, b): + return tuple(a[i] + b[i] for i in range(3)) + + +def _mul(a, scale): + return tuple(v * scale for v in a) + + +def _cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def _unit(a): + length = sqrt(sum(v * v for v in a)) + return tuple(v / length for v in a) + + +def _frame(axis): + w = _unit(axis) + reference = (0, 0, 1) if abs(w[2]) < .9 else (0, 1, 0) + u = _unit(_cross(reference, w)) + return u, _cross(w, u), w + + +def _lathe(name, loc, profile, mat, axis=(0, 0, 1), segments=10): + """Closed profile, including real inner walls; zero radii become poles. + + Profile travels from the back/bottom up the outside, down the inside. + Independent pole vertices avoid degenerate zero-area triangles. + """ + u, v, w = _frame(axis) + verts, loops, faces = [], [], [] + for radius, depth in profile: + if radius == 0: + loops.append([len(verts)]) + verts.append(_add(loc, _mul(w, depth))) + continue + loop = [] + for k in range(segments): + angle = 2 * pi * k / segments + offset = _add(_mul(w, depth), + _add(_mul(u, radius * cos(angle)), + _mul(v, radius * sin(angle)))) + loop.append(len(verts)) + verts.append(_add(loc, offset)) + loops.append(loop) + for j in range(len(loops)): + low, high = loops[j], loops[(j + 1) % len(loops)] + if len(low) == 1 and len(high) == 1: + continue + for k in range(segments): + nxt = (k + 1) % segments + if len(low) == 1: + faces.append((low[0], high[nxt], high[k])) + elif len(high) == 1: + faces.append((low[k], low[nxt], high[0])) + else: + faces.append((low[k], low[nxt], high[nxt], high[k])) + mesh_object(name, verts, faces, mat) + + +def _cup(name, loc, radius, depth, mat, axis=(0, 0, 1), segments=10): + # The rim is 13% thick; the inset bottom is visible from above/front. + _lathe(name, loc, [(0, 0), (radius * .5, .04), + (radius * .73, depth * .35), (radius, depth), + (radius * .87, depth), (radius * .59, depth * .35), + (0, depth * .20)], mat, axis, segments) + + +def _horn(name, loc, radius, depth, mat, axis=(0, -1, .18)): + _lathe(name, loc, [(radius * .16, 0), (radius * .25, depth * .42), + (radius * .58, depth * .76), (radius, depth), + (radius * .84, depth), (radius * .43, depth * .72), + (radius * .1, depth * .35), (0, depth * .29), + (0, 0)], mat, axis, 10) + + +def _spike(name, start, end, radius, mat, sides=5): + axis = tuple(end[i] - start[i] for i in range(3)) + u, v, _ = _frame(axis) + verts = [_add(start, _add(_mul(u, radius * cos(2 * pi * k / sides)), + _mul(v, radius * sin(2 * pi * k / sides)))) + for k in range(sides)] + verts.append(end) + faces = [tuple(reversed(range(sides)))] + faces.extend((k, (k + 1) % sides, sides) for k in range(sides)) + mesh_object(name, verts, faces, mat) + + +def _leaf(name, loc, width, height, mat, lean=0): + # Thick diamond leaf: large central ridge, only eight triangles. + x, y, z = loc + verts = [(x, y, z), (x - width / 2, y, z + height * .42), + (x + lean, y + .05, z + height), + (x + width / 2, y, z + height * .42), + (x + lean * .3, y - .09, z + height * .45), + (x + lean * .3, y + .055, z + height * .45)] + faces = [(0, 4, 1), (1, 4, 2), (2, 4, 3), (3, 4, 0), + (1, 5, 0), (2, 5, 1), (3, 5, 2), (0, 5, 3)] + mesh_object(name, verts, faces, mat) + + +def _eyes(loc, mat, spread=.075, scale=.038): + for side, suffix in ((-1, "L"), (1, "R")): + p = (loc[0] + side * spread, loc[1], loc[2]) + ellipsoid("Head_Eye" + suffix, p, (scale, .023, scale * .75), mat) + + +def _mask(name, loc, scale, mat, eyes_mat): + ellipsoid(name, loc, (.15 * scale, .075 * scale, .22 * scale), mat) + for sign, suffix in ((-1, "L"), (1, "R")): + ellipsoid(name + "_Eye" + suffix, + (loc[0] + sign * .052 * scale, loc[1] - .071 * scale, + loc[2] + .023 * scale), + (.028 * scale, .012 * scale, .046 * scale), eyes_mat) + + +def _basalt_legs(mat, wide=False): + spread = .32 if wide else .22 + for side, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Leg" + suffix + "_Foot", (side * spread, -.075, .12), + (.20 if wide else .15, .24, .12), mat) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .15), + (side * spread * .7, .02, .49), .095, mat, vertices=6) + + +def _mechanical_legs(mat, wide=False): + spread = .27 if wide else .20 + for side, suffix in ((-1, "L"), (1, "R")): + box("Leg" + suffix + "_Foot", (side * spread, -.07, .07), + (.22, .33, .14), mat["accent"]) + beam("Leg" + suffix + "_Shin", (side * spread, 0, .14), + (side * spread, .08, .35), .065, mat["accent"], vertices=6) + ellipsoid("Leg" + suffix + "_Knee", (side * spread, .08, .35), + (.10, .10, .10), mat["secondary"]) + beam("Leg" + suffix + "_Thigh", (side * spread, .08, .35), + (side * spread * .66, 0, .57), .09, mat["primary"], vertices=6) + + +def _root_feet(mat, count=4, spread=.43, top=.60): + for k in range(count): + a = 2 * pi * k / count + pi / 4 + base = (spread * cos(a), spread * sin(a), .055) + elbow = (spread * .6 * cos(a), spread * .6 * sin(a), .24) + suffix = str(k + 1) + beam("Leg_Root" + suffix, base, elbow, .09, mat, vertices=5) + beam("Leg_RootUpper" + suffix, elbow, (0, .02, top), .12, + mat, vertices=5) + ellipsoid("Leg_RootToe" + suffix, base, (.16, .10, .055), mat) + + +def _mist_robe(mat, upgraded=False): + # Alternating long cloth points touch the floor; the upper body floats. + cone("Body_Robe", (0, .035, .49), .31 if upgraded else .25, + .13, .74, mat["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + _spike("Body_ClothPoint" + str(k), + (.16 * cos(a), .035 + .16 * sin(a), .35), + (.31 * cos(a), .035 + .27 * sin(a), .015), .11, + mat["secondary"] if k % 2 else mat["primary"]) + ellipsoid("Body_Chest", (0, 0, .90), (.23, .16, .23), mat["secondary"]) + + +def _glut_ranged(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_Core", (0, .035, .69), (.30 if up else .21, .22, .27), + m["primary"]) + ellipsoid("Head_Helm", (0, -.015, 1.12), (.19, .16, .20), m["light"]) + _eyes((0, -.17, 1.13), m["secondary"]) + box("Body_Ember", (0, -.197, .71), (.11, .045, .19), m["secondary"]) + if up: + # Broad glass bow arms distinguish the upgrade from the slender lance. + box("Weapon_Rail", (0, -.20, .96), (.10, .98, .09), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .2, 0, .88), (s * .30, -.15, .91), + .075, m["primary"], vertices=6) + _spike("Weapon_GlassBow" + suffix, (s * .06, -.25, .99), + (s * .62, -.04, 1.25), .16, m["secondary"]) + beam("Weapon_String" + suffix, (s * .62, -.04, 1.25), + (0, .22, 1.03), .012, m["light"], vertices=4) + beam("Weapon_Bolt", (0, .20, 1.02), (0, -.64, 1.02), .025, m["light"]) + _spike("Weapon_BoltHead", (0, -.57, 1.02), (0, -.80, 1.02), + .08, m["secondary"]) + else: + beam("ArmL", (-.15, 0, .89), (-.25, -.07, .70), .07, m["primary"]) + beam("ArmR", (.15, 0, .90), (.30, -.19, .91), .075, m["primary"]) + beam("Weapon_Lance", (.29, .34, .81), (.29, -.60, 1.05), .038, + m["accent"]) + _spike("Weapon_GlassTip", (.29, -.53, 1.03), (.29, -.81, 1.11), + .105, m["secondary"]) + + +def _nieten_ranged(up, m): + _mechanical_legs(m) + cone("Body_Cuirass", (0, .02, .78), .21, .27, .43, m["primary"], vertices=6) + box("Body_Plate", (0, -.18, .80), (.27, .09, .22), m["secondary"]) + beam("Head_Neck", (0, 0, 1.0), (0, 0, 1.10), .075, m["accent"]) + box("Head_Housing", (0, -.015, 1.22), (.29, .25, .25), m["light"]) + box("Head_Visor", (0, -.146, 1.23), (.18, .028, .05), m["primary"]) + weapon_x = 0 if up else .29 + beam("ArmL", (-.21, 0, .92), (-.28, -.13, .77), .065, m["accent"]) + beam("ArmR", (.21, 0, .92), (weapon_x + .07, -.24, .91), .065, + m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Weapon_Rail" + suffix, (weapon_x + s * .055, -.30, .97), + (.055, .82 if up else .61, .07), m["accent"]) + tip = (weapon_x + s * (.44 if up else .23), -.27, .97) + beam("Weapon_Bow" + suffix, (weapon_x, -.43, .97), tip, .055, + m["secondary"], vertices=6) + beam("Weapon_String" + suffix, tip, (weapon_x, .02, .97), .011, + m["light"], vertices=4) + _spike("Weapon_Bolt", (weapon_x, -.44, .98), + (weapon_x, -.78 if up else -.66, .98), .052, m["light"]) + if up: + box("Weapon_Sight", (0, -.13, 1.08), (.08, .25, .09), m["primary"]) + _spike("Head_Crest", (0, .03, 1.34), (0, .10, 1.58), .075, + m["secondary"]) + for s, suffix in ((-1, "L"), (1, "R")): + box("Arm" + suffix + "_Pauldron", (s * .27, .01, .96), + (.16, .25, .13), m["secondary"]) + + +def _nebel_ranged(up, m): + _mist_robe(m, up) + _mask("Head_Mask", (0, -.105, 1.18), 1.0, m["light"], m["primary"]) + _leaf("Head_Hood", (0, .055, 1.16), .35, .37, m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, 0, .94), (s * .31, -.18, .77), + .055, m["secondary"], vertices=5) + horn_sides = (-1, 1) if up else (1,) + for s in horn_sides: + suffix = "L" if s < 0 else "R" + root = (s * .25, -.12, .79) + elbow = (s * .46, .07, 1.08 if up else .97) + mouth = (s * (.48 if up else .31), -.03, 1.27 if up else 1.02) + beam("Weapon_HornStem" + suffix, root, elbow, .055, m["secondary"]) + beam("Weapon_HornCurve" + suffix, elbow, mouth, .072, m["light"]) + _horn("Weapon_HornBell" + suffix, mouth, .19 if up else .16, + .40 if up else .49, m["light"]) + axis = _unit((0, -1, .18)) + lip = _add(mouth, _mul(axis, .39 if up else .48)) + _lathe("Weapon_MintLip" + suffix, lip, + [(.19 if up else .16, 0), (.19 if up else .16, .025), + (.16 if up else .132, .025), (.16 if up else .132, 0)], + m["accent"], axis) + + +def _wurzel_ranged(up, m): + _root_feet(m["primary"], 3, .34, .56) + ellipsoid("Body_Trunk", (0, .025, .76), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.025, 1.13), (.17, .15, .20), m["secondary"]) + _eyes((0, -.17, 1.13), m["accent"], spread=.057, scale=.03) + _leaf("Body_LeafMantle", (0, -.14, .59), .43, .40, m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + shoulder = (s * .17, 0, .91) + hand = (s * .29, -.21, .85) + beam("Arm" + suffix, shoulder, hand, .07, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .26, -.13, .81), .21, .26, + m["secondary"], lean=s * .1) + beam("Weapon_VineLower", (.28, -.17, .73), (.44, -.08, .93), .046, + m["primary"], vertices=5) + beam("Weapon_VineUpper", (.44, -.08, .93), (.40, -.17, 1.17), .04, + m["primary"], vertices=5) + _cup("Weapon_SeedCapsule", (.24, -.19, .88), .19 if up else .15, + .20, m["accent"], axis=(0, -.7, .7), segments=8) + ellipsoid("Weapon_Seed", (.24, -.30, 1.02), (.075, .075, .10), m["light"]) + if up: + # Overlapping tiers make a pinecone crown, not a mushroom cap. + for layer in range(3): + z = 1.24 + layer * .10 + radius = .23 - layer * .035 + cone("Head_ConeTier" + str(layer), (0, .025, z), radius, + radius * .47, .16, m["primary"], vertices=7) + for k in range(5): + a = 2 * pi * k / 5 + layer * .3 + _leaf("Head_ConeScale" + str(layer) + "_" + str(k), + (radius * .75 * cos(a), .025 + radius * .75 * sin(a), z - .05), + .11, .16, m["accent"]) + else: + _leaf("Head_LeafCrest", (0, .04, 1.22), .22, .25, m["accent"], .08) + + +def _glut_artillery(up, m): + _basalt_legs(m["primary"], True) + ellipsoid("Body_Foundation", (0, .025, .48), (.39, .31, .22), m["primary"]) + _cup("Weapon_Crater", (0, .02, .52), .55 if up else .43, + .63 if up else .50, m["primary"], segments=12) + _cup("Weapon_EmberLining", (0, .02, .66), .37 if up else .29, + .24 if up else .20, m["secondary"], segments=10) + for s, suffix in ((-1, "L"), (1, "R")): + ellipsoid("Arm" + suffix + "_Slab", (s * .39, .0, .65), + (.13, .19, .25), m["primary"]) + ellipsoid("Head_Eye" + suffix, (s * .13, -.28, .53), + (.055, .025, .035), m["secondary"]) + for k in range(3 if up else 2): + ellipsoid("Weapon_Coal" + str(k), + ((k - (1 if up else .5)) * .12, .015, .80 if up else .77), + (.105, .10, .10), m["accent"]) + if up: + for k in range(5): + a = .2 + pi * k / 4 + _spike("Body_CraterFin" + str(k), + (.40 * cos(a), .03 + .39 * sin(a), .87), + (.46 * cos(a), .03 + .43 * sin(a), 1.37), .095, + m["primary"]) + + +def _nieten_artillery(up, m): + _mechanical_legs(m, True) + box("Body_Chassis", (0, .035, .67), (.56 if up else .45, .37, .34), + m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Piston", (s * .25, .1, .60), + (s * .34, .17, .96), .065, m["accent"]) + cylinder("Arm" + suffix + "_Collar", (s * .31, .15, .84), .095, + .15, m["secondary"], vertices=8) + bell_positions = (-.29, .29) if up else (0,) + for i, x in enumerate(bell_positions): + base = (x, .08, .92) + _horn("Weapon_Resonator" + str(i), base, .27 if up else .34, + .48, m["secondary"], axis=(0, -1, .3)) + # A dark interior cavity and a slim central piston remain visible. + beam("Weapon_Clapper" + str(i), (x, .045, .94), (x, -.26, 1.035), + .038, m["accent"]) + ellipsoid("Weapon_ClapperHead" + str(i), (x, -.27, 1.04), + (.09, .07, .09), m["light"]) + box("Head_Visor", (0, -.164, .68), (.20, .03, .075), m["light"]) + for x, suffix in ((-.24, "L"), (.24, "R")): + cylinder("Body_Exhaust" + suffix, (x, .25, 1.03), .075, + .50 if up else .34, m["accent"], vertices=8) + if up: + box("Body_Brow", (0, -.10, 1.34), (.66, .14, .085), m["primary"]) + cone("Head_Metronome", (0, -.03, 1.47), .10, 0, .20, + m["light"], vertices=4) + + +def _nebel_artillery(up, m): + # Face forward/slightly up: the cavity remains visible to an elevated camera. + _mist_robe(m, up) + bell_base = (0, -.16, 1.05 if up else .85) + radius, depth = (.45, .60) if up else (.38, .50) + _horn("Body_CathedralBell", bell_base, radius, depth, + m["light"], axis=(0, -1, .12)) + beam("Weapon_ClapperStem", (0, -.27, 1.09 if up else .90), + (0, -.70 if up else -.60, 1.0 if up else .80), .045, m["accent"]) + ellipsoid("Weapon_Clapper", (0, -.73 if up else -.63, 1.0 if up else .80), + (.13, .10, .13), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .18, .02, .96), + (s * .44, -.08, .63), .07, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .44, -.08, .63), + (s * .49, -.19, .94), .10, m["primary"]) + _mask("Head_Mask", (0, .035, 1.49 if up else 1.38), .65, + m["secondary"], m["accent"]) + if up: + for i, x in enumerate((-.27, 0, .27)): + beam("Head_SpireBase" + str(i), (x * .65, .08, 1.16), + (x, .09, 1.42), .075, m["primary"], vertices=5) + _spike("Head_Spire" + str(i), (x, .09, 1.40), + (x * .65, -.01, 1.71 if i == 1 else 1.59), + .075, m["light"]) + + +def _mushroom(name, loc, radius, height, m): + x, y, z = loc + cone(name + "_Stem", (x, y, z + height * .45), .095, .07, height * .9, + m["primary"], vertices=7) + # An angular overhanging cap and light gill ring form a readable roof. + cone(name + "_Gills", (x, y, z + height * .86), radius * .91, + radius * .5, .10, m["accent"], vertices=10) + cone(name + "_Cap", (x, y, z + height), radius, radius * .15, + .22, m["light"], vertices=10) + + +def _wurzel_artillery(up, m): + _root_feet(m["primary"], 5, .50 if up else .43, .56) + ellipsoid("Body_Moss", (0, .02, .48), (.32, .26, .18), m["secondary"]) + _cup("Weapon_SporeChalice", (0, -.10, .50), .40 if up else .43, + .43, m["light"], segments=12) + _cup("Weapon_SporeInterior", (0, -.10, .60), .28, .18, + m["secondary"], segments=10) + for i, x in enumerate((-.105, .105)): + ellipsoid("Weapon_Spore" + str(i), (x, -.08, .81), + (.06, .06, .075), m["accent"]) + for s, suffix in ((-1, "L"), (1, "R")): + _leaf("Arm" + suffix + "_Leaf", (s * .30, -.05, .46), .20, .36, + m["accent"], lean=s * .14) + if up: + _mushroom("Body_RoofL", (-.34, .12, .47), .30, .67, m) + _mushroom("Body_RoofR", (.34, .18, .47), .29, .81, m) + _mushroom("Body_RoofCrown", (0, .33, .54), .39, .98, m) + for x, suffix in ((-.12, "L"), (.12, "R")): + beam("Body_Buttress" + suffix, (x * 3, .33, .12), + (x, .31, 1.21), .075, m["primary"], vertices=5) + + +def _glut_support(up, m): + _basalt_legs(m["primary"], up) + ellipsoid("Body_FurnaceBack", (0, .11, .79), + (.34 if up else .28, .20, .37), m["primary"]) + _cup("Body_OpenHearth", (0, .015, .85), .28 if up else .23, + .33, m["accent"], axis=(0, -1, 0), segments=8) + ellipsoid("Body_Ember", (0, -.10, .85), (.12, .085, .15), m["secondary"]) + ellipsoid("Head_Capstone", (0, .01, 1.17), (.21, .17, .15), m["light"]) + _eyes((0, -.15, 1.16), m["secondary"], spread=.075) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .26, .01, .92), + (s * .33, -.33, .63), .09, m["primary"], vertices=6) + _cup("Weapon_WarmingBowl", (0, -.38, .52), .36 if up else .29, + .22, m["accent"], segments=10) + ellipsoid("Weapon_WarmCoal", (0, -.38, .61), (.15, .12, .07), + m["secondary"]) + if up: + # Upper-half sun rays stay behind the face, safely within the footprint. + for k in range(7): + a = pi * k / 6 + start = (.30 * cos(a), .09, 1.12 + .30 * sin(a)) + end = (.48 * cos(a), .11, 1.12 + .48 * sin(a)) + _spike("Head_SunRay" + str(k), start, end, .065, m["accent"]) + cone("Head_Crown", (0, .0, 1.34), .16, .23, .12, + m["accent"], vertices=8) + + +def _nieten_support(up, m): + _mechanical_legs(m, up) + cone("Body_Coat", (0, .02, .73), .37 if up else .24, + .20, .51, m["primary"], vertices=6) + box("Body_PendulumCase", (0, -.18, .79), (.18, .10, .30), m["secondary"]) + beam("Body_Pendulum", (0, -.24, .89), (.045, -.24, .64), .018, m["accent"]) + ellipsoid("Body_PendulumWeight", (.045, -.24, .65), (.07, .035, .07), + m["light"]) + ellipsoid("Head_Casing", (0, .015, 1.14), (.17, .14, .17), m["accent"]) + ellipsoid("Head_Dial", (0, -.119, 1.14), (.135, .025, .135), m["light"]) + beam("Head_DialHand", (0, -.15, 1.14), (.055, -.15, 1.22), .015, + m["primary"], vertices=4) + for s, suffix in ((-1, "L"), (1, "R")): + elbow = (s * .35, .0, .91) + hand = (s * .45, -.13, 1.10 if s > 0 else .89) + beam("Arm" + suffix + "_Upper", (s * .2, .02, .95), elbow, .06, + m["accent"]) + beam("Arm" + suffix + "_Fore", elbow, hand, .047, m["secondary"]) + ellipsoid("Arm" + suffix + "_Hand", hand, (.065, .065, .065), m["light"]) + beam("Weapon_Baton", (.45, -.13, 1.06), (.61, -.22, 1.45), .019, + m["light"], vertices=5) + if up: + for k, x in enumerate((-.18, 0, .18)): + _spike("Head_CrownTine" + str(k), (x, .015, 1.28), + (x, .015, 1.56 if k == 1 else 1.47), .06, + m["secondary"]) + box("Head_MetronomeBridge", (0, .015, 1.36), (.45, .12, .07), + m["secondary"]) + for s in (-1, 1): + _leaf("Body_CoatTail" + str(s), (s * .20, .20, .33), .24, .59, + m["secondary"], lean=s * .16) + else: + _spike("Head_Spindle", (0, .015, 1.28), (0, .015, 1.45), .055, + m["secondary"]) + + +def _nebel_support(up, m): + _mist_robe(m, up) + _mask("Head_MainMask", (0, -.13, 1.17), 1.0, m["light"], m["primary"]) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix + "_Lower", (s * .17, 0, .88), + (s * .37, -.04, .82), .062, m["secondary"], vertices=5) + _spike("Arm" + suffix + "_Sickle", (s * .37, -.04, .82), + (s * .49, -.04, 1.21), .095, m["primary"]) + _leaf("Body_SickleCollar" + suffix, (s * .13, .02, .88), .29, + .43 if up else .29, m["secondary"], lean=s * .29) + if up: + positions = ((-.51, -.035, 1.46), (0, .11, 1.65), (.51, -.035, 1.46)) + for i, p in enumerate(positions): + _mask("Head_CompanionMask" + str(i), p, .67, + m["light"], m["primary"]) + for i, x in enumerate((-.12, 0, .12)): + _spike("Head_Crown" + str(i), (x, -.035, 1.31), + (x * 1.2, -.035, 1.53 if i == 1 else 1.45), .045, + m["accent"]) + else: + _mask("Head_CompanionMask0", (.49, -.035, 1.44), .70, + m["light"], m["primary"]) + ellipsoid("Body_ChoirGem", (0, -.19, .83), (.055, .035, .09), m["accent"]) + + +def _flower(name, loc, scale, m): + for k in range(5): + a = 2 * pi * k / 5 + ellipsoid(name + "_Petal" + str(k), + (loc[0] + cos(a) * .09 * scale, + loc[1] + sin(a) * .09 * scale, loc[2]), + (.085 * scale, .07 * scale, .035 * scale), m["light"]) + ellipsoid(name + "_Heart", (loc[0], loc[1], loc[2] + .025 * scale), + (.052 * scale, .052 * scale, .035 * scale), m["accent"]) + + +def _wurzel_support(up, m): + _root_feet(m["primary"], 5 if up else 3, .45 if up else .31, .55) + # Two counter-leaning stems create an open woven body in the upgrade. + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_WovenRoot" + suffix, (s * .20, .02, .38), + (-s * .17, .015, .83), .105, m["primary"], vertices=5) + beam("Body_WovenRootTop" + suffix, (-s * .17, .015, .83), + (s * .11, .025, 1.16), .085, m["primary"], vertices=5) + else: + ellipsoid("Body_Trunk", (0, .025, .72), (.19, .16, .29), m["primary"]) + ellipsoid("Head_Seed", (0, -.03, 1.12), (.15, .14, .18), m["secondary"]) + _eyes((0, -.17, 1.12), m["accent"], spread=.05, scale=.026) + for s, suffix in ((-1, "L"), (1, "R")): + beam("Arm" + suffix, (s * .15, 0, .94), + (s * .28, -.27, .69), .065, m["primary"], vertices=5) + _leaf("Arm" + suffix + "_Leaf", (s * .23, -.21, .68), .21, .28, + m["secondary"], lean=s * .12) + _cup("Weapon_LeafBasin", (0, -.31, .62), .30 if up else .23, + .20, m["accent"], segments=8) + # Water uses the optional shared mint accent, with a leaf-colour fallback. + # Opaque faceted geometry avoids sorting issues until the VFX integration. + water = m.get("water", m["accent"]) + cylinder("Weapon_Pool", (0, -.31, .739), .21 if up else .145, + .025, water, vertices=10) + ellipsoid("Weapon_Dew", (0, -.31, .86), (.085, .075, .13), water) + _spike("Weapon_DewTip", (0, -.31, .93), (0, -.31, 1.035), .059, water) + if up: + for s, suffix in ((-1, "L"), (1, "R")): + beam("Body_CanopyStem" + suffix, (s * .17, .11, .88), + (s * .36, .14, 1.28), .055, m["primary"], vertices=5) + _leaf("Head_Canopy" + suffix, (s * .12, .10, 1.17), .56, .36, + m["secondary"], lean=s * .28) + _flower("Head_Flower" + suffix, (s * .31, .12, 1.43), 1.0, m) + _flower("Head_FlowerCrown", (0, .07, 1.53), .9, m) + else: + _leaf("Head_LeafCap", (0, .02, 1.23), .33, .25, m["accent"], -.06) + + +_RANGED = {"glutpakt": _glut_ranged, "nietenkonvent": _nieten_ranged, + "nebelchor": _nebel_ranged, "wurzelbund": _wurzel_ranged} +_ARTILLERY = {"glutpakt": _glut_artillery, "nietenkonvent": _nieten_artillery, + "nebelchor": _nebel_artillery, "wurzelbund": _wurzel_artillery} +_SUPPORT = {"glutpakt": _glut_support, "nietenkonvent": _nieten_support, + "nebelchor": _nebel_support, "wurzelbund": _wurzel_support} + + +def build_ranged(spec, mat): + """Build IDs *05 (base) and *06 (upgraded).""" + _RANGED[spec["faction"]](spec["upgraded"], mat) + + +def build_artillery(spec, mat): + """Build IDs *07 (base) and *08 (upgraded).""" + _ARTILLERY[spec["faction"]](spec["upgraded"], mat) + + +def build_support(spec, mat): + """Build IDs *09 (base) and *10 (upgraded).""" + _SUPPORT[spec["faction"]](spec["upgraded"], mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_tank.py b/assets-source/phase4/standalone/create_tank.py new file mode 100644 index 0000000..4b27b56 --- /dev/null +++ b/assets-source/phase4/standalone/create_tank.py @@ -0,0 +1,3427 @@ +"""Saumwacht · Tank · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'g03' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'g03', + 'name': 'Schlackenwacht', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'tank', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_g03.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'g04', + 'name': 'Basaltbastion', + 'faction': 'glutpakt', + 'palette': 'glutpakt', + 'role': 'tank', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_g04.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'm01', + 'name': 'Kesselwicht', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'tank', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_m01.glb'}, + {'id': 'm02', + 'name': 'Druckhüter', + 'faction': 'nietenkonvent', + 'palette': 'nietenkonvent', + 'role': 'tank', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_m02.glb'}, + {'id': 'n01', + 'name': 'Saummaske', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'tank', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_n01.glb'}, + {'id': 'n02', + 'name': 'Grenzmaske', + 'faction': 'nebelchor', + 'palette': 'nebelchor', + 'role': 'tank', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_n02.glb'}, + {'id': 'w03', + 'name': 'Korkrücken', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'tank', + 'upgraded': False, + 'height': 1.35, + 'footprint': 1.85, + 'file': 'unit_w03.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}, + {'id': 'w04', + 'name': 'Ringborke', + 'faction': 'wurzelbund', + 'palette': 'wurzelbund', + 'role': 'tank', + 'upgraded': True, + 'height': 1.5, + 'footprint': 1.85, + 'file': 'unit_w04.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, sin, pi + + + +def _profile(name, points, y, depth, mat): + """Extrude a silhouette with outward normals and a centred editable origin.""" + signed_area = sum(points[i][0] * points[(i+1) % len(points)][1] + - points[(i+1) % len(points)][0] * points[i][1] + for i in range(len(points))) + if signed_area < 0: + points = list(reversed(points)) + center_x = (min(p[0] for p in points) + max(p[0] for p in points)) / 2 + center_z = (min(p[1] for p in points) + max(p[1] for p in points)) / 2 + n = len(points) + vertices = [(x-center_x, -depth/2, z-center_z) for x, z in points] + vertices += [(x-center_x, depth/2, z-center_z) for x, z in points] + faces = [tuple(range(n)), tuple(range(2 * n - 1, n - 1, -1))] + faces += [(i, i + n, (i + 1) % n + n, (i + 1) % n) for i in range(n)] + obj = mesh_object(name, vertices, faces, mat) + obj.location = (center_x, y, center_z) + return obj + + +def _slab(name, loc, size, mat, bevel=0.08): + """Eight-sided shield / armour plate with real clipped corners.""" + x, y, z = loc + w, d, h = size + a, b = w / 2, h / 2 + c = min(bevel, a * 0.42, b * 0.42) + points = [(x-a+c, z-b), (x+a-c, z-b), (x+a, z-b+c), + (x+a, z+b-c), (x+a-c, z+b), (x-a+c, z+b), + (x-a, z+b-c), (x-a, z-b+c)] + return _profile(name, points, y, d, mat) + + +def _blade(name, origin, length, width, angle, mat, depth=0.055, hook=0.12): + """A broad bent blade, with an unmistakable edge rather than a thin rod.""" + x, y, z = origin + local = [(-width*.38, 0), (width*.48, 0), + (width*.54, length*.52), (hook, length), + (-width*.30, length*.65)] + points = [(x + u*cos(angle) + v*sin(angle), + z - u*sin(angle) + v*cos(angle)) for u, v in local] + return _profile(name, points, y, depth, mat) + + +def _crescent(name, origin, radius, thickness, start, end, mat, + depth=0.09, segments=10): + """An open polygonal crescent plate in the front plane, angles in radians.""" + x, y, z = origin + angles = [start + (end-start)*i/segments for i in range(segments+1)] + points = [(x + radius*cos(a), z + radius*sin(a)) for a in angles] + points += [(x + (radius-thickness)*cos(a), + z + (radius-thickness)*sin(a)) for a in reversed(angles)] + return _profile(name, points, y, depth, mat) + + +def _eyes(prefix, x, y, z, spacing, mat, width=0.085): + for side, s in (("L", -1), ("R", 1)): + box(prefix + "Eye" + side, (x+s*spacing, y, z), + (width, 0.023, 0.028), mat) + + +def _stone_legs(mat, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (0.27 if upgraded else 0.24) + _slab("Leg" + side + "Shin", (x, 0.02, 0.26), + (0.30, 0.31, 0.36), mat["primary"]) + _slab("Leg" + side + "Foot", (x, -0.10, 0.095), + (0.37, 0.46, 0.19), mat["primary"], 0.07) + if upgraded: + box("Leg" + side + "Cuff", (x, -0.167, 0.27), + (0.23, 0.035, 0.07), mat["accent"]) + + +def _coal_body(mat, upgraded): + ellipsoid("BodyCoal", (0, 0.01, 0.77), (0.44, 0.35, 0.48), + mat["primary"], subdivisions=2) + _slab("BodyForehead", (0, -0.16, 1.115), (0.62, 0.36, 0.25), + mat["primary"]) + mouth = [(-.31,.83), (-.23,.77), (-.12,.80), (0,.735), + (.13,.785), (.24,.76), (.31,.83), (.25,.94), + (.1,.92), (0,.97), (-.14,.93), (-.27,.955)] + _profile("HeadEmberMouth", mouth, -.352, .045, mat["secondary"]) + _eyes("Head", 0, -.350, 1.05, .155, mat["secondary"], .065) + for i, x in enumerate((-.20, 0, .20)): + _profile("HeadTooth%02d" % i, + [(x-.035,.94), (x,.865), (x+.035,.94)], + -.384, .025, mat["light"]) + for side, s in (("L", -1), ("R", 1)): + if upgraded: + _slab("BodyShoulder" + side, (s*.49, .0, 1.08), + (.39, .47, .32), mat["primary"]) + _blade("BodyShoulderCrest" + side, (s*.42, .035, 1.15), + .29, .16, s*.50, mat["primary"], .17, s*.04) + box("BodyShoulderSeam" + side, (s*.50, -.243, 1.05), + (.22, .02, .055), mat["secondary"]) + else: + ellipsoid("BodyShoulder" + side, (s*.41, .02, .87), + (.19, .25, .25), mat["primary"]) + + +def _coal_claws(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Upper", (s*.37, .0, .86), + (s*.55, -.075, .65), .13, mat["primary"]) + ellipsoid("Arm" + side + "Fist", (s*.57, -.16, .56), + (.19, .24, .19), mat["primary"]) + for i, dx in enumerate((-.105, .105)): + x = s*.57 + dx + # Curved front claws are separate wedges; upgrade adds long tips. + points = [(x-.045,.60), (x+.045,.60), (x+.065,.42), + (x+.015,.30 if upgraded else .37), + (x-.035,.43)] + _profile("Weapon" + side + "Claw%02d" % i, points, + -.39 if upgraded else -.34, .115, + mat["accent"] if upgraded else mat["light"]) + if upgraded: + _slab("Arm" + side + "WristGuard", (s*.57, -.18, .70), + (.33, .40, .13), mat["accent"], .045) + + +def _basalt_body(mat, upgraded): + _slab("BodyBastion", (0, .035, .83), + (1.02 if upgraded else .87, .57, .95), mat["primary"]) + _slab("BodyFrontShield", (0, -.30, .80), (.74, .18, .71), + mat["primary"], .14) + _slab("HeadFurnaceSlot", (0, -.401, 1.07), (.48, .035, .085), + mat["secondary"], .025) + for s in (-1, 1): + beam("BodyBrace" + ("L" if s < 0 else "R"), + (s*.29, -.398, .50), (s*.29, -.398, .95), + .033, mat["accent"], vertices=4) + if upgraded: + for i, (x, z, width) in enumerate(((-.48, 1.20, .31), + (0, 1.30, .43), + (.48, 1.20, .31))): + _slab("BodyBattlement%02d" % i, (x, .035, z), + (width, .54, .35), mat["primary"], .05) + box("BodyBattlementCap%02d" % i, (x, .035, z+.145), + (width+.025, .565, .055), mat["accent"]) + _slab("BodyShieldBoss", (0, -.41, .73), (.38, .075, .35), + mat["accent"], .095) + _slab("BodyShieldCore", (0, -.456, .73), (.23, .025, .22), + mat["secondary"], .065) + + +def _basalt_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + x = s * (.635 if upgraded else .54) + _slab("Arm" + side + "Pillar", (x, .01, .72), + (.28, .37, .60), mat["primary"]) + _slab("Arm" + side + "Fist", (x, -.075, .48), + (.32, .42, .27), mat["primary"]) + box("Arm" + side + "Band", (x, -.287, .52), + (.23, .028, .07), mat["accent"]) + + +def _machine_legs(mat, upgraded=False, tall=False): + for side, s in (("L", -1), ("R", 1)): + x = s * (.25 if tall else .24) + top = .72 if tall else .46 + knee = (x*1.15, .03, .38 if tall else .25) + ankle = (x, -.065, .13) + beam("Leg" + side + "PistonUpper", (x*.8, .035, top), knee, + .07 if tall else .13, mat["accent"]) + beam("Leg" + side + "PistonLower", knee, ankle, + .055 if tall else .09, mat["accent"]) + cylinder("Leg" + side + "Knee", knee, .085 if tall else .13, + .16, mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + _slab("Leg" + side + "Shoe", (x, -.105, .065), + (.23 if tall else .33, .36, .13), mat["primary"], .04) + if upgraded: + _slab("Leg" + side + "Greave", (x, -.115, .25), + (.17 if tall else .27, .12, .23), mat["primary"], .04) + + +def _machine_mask(mat, z=1.22): + _profile("HeadCeramicMask", [(-.14,z-.11), (.14,z-.11), + (.17,z+.06), (0,z+.18), (-.17,z+.06)], + -.205, .12, mat["light"]) + _eyes("Head", 0, -.272, z+.025, .067, mat["primary"], .060) + + +def _shear_body(mat, upgraded): + ellipsoid("BodySpindle", (0, .02, .91), + (.285 if upgraded else .21, .235, .32), mat["primary"]) + cylinder("BodyOcherHub", (0, -.224, .87), .14, .07, + mat["secondary"], vertices=10, rotation=(pi/2, 0, 0)) + cylinder("BodyHubPin", (0, -.267, .87), .057, .025, + mat["accent"], vertices=8, rotation=(pi/2, 0, 0)) + _machine_mask(mat, 1.235) + if upgraded: + _slab("BodyHubArmor", (0, .15, .98), (.57, .21, .37), + mat["primary"]) + cone("HeadFin", (0, .055, 1.385), .065, 0, .21, + mat["secondary"], vertices=4) + + +def _shear_weapons(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + if upgraded: + for i, (z, angle) in enumerate(((1.10, .62), (.89, 1.32), + (.66, 2.07))): + pivot = (s*.47, -.105, z) + beam("Arm" + side + "Link%02d" % i, + (s*.21, .02, .93), pivot, .049, mat["secondary"]) + cylinder("Arm" + side + "Hub%02d" % i, pivot, .076, + .10, mat["secondary"], vertices=8, + rotation=(pi/2, 0, 0)) + _blade("Weapon" + side + "Blade%02d" % i, + (pivot[0], -.17, z), .39, .105, s*angle, + mat["accent"], .055, s*.07) + else: + pivot = (s*.43, -.12, .95) + beam("Arm" + side + "Upper", (s*.16, .025, 1.0), + (s*.34, .04, .82), .065, mat["secondary"]) + beam("Arm" + side + "Forearm", (s*.34, .04, .82), + pivot, .060, mat["primary"]) + for i, angle in enumerate((.39, 1.07)): + _blade("Weapon" + side + "Shear%02d" % i, + (pivot[0], -.19-i*.045, pivot[2]), .42, .10, + s*angle, mat["accent"], .055, s*.035) + cylinder("Weapon" + side + "ShearPivot", (s*.43, -.264, .95), + .092, .055, mat["secondary"], vertices=10, + rotation=(pi/2, 0, 0)) + + +def _boiler_body(mat, upgraded): + cylinder("BodyBoiler", (0, .01, .77), .385, .66, + mat["primary"], vertices=12) + cone("BodyBoilerLid", (0, .01, 1.115), .39, .27, .14, + mat["primary"], vertices=12) + ring("BodyLowerRim", (0, .01, .475), .38, .035, + mat["secondary"], segments=12) + _slab("HeadCeramicFace", (0, -.355, .98), (.32, .105, .19), + mat["light"], .04) + _eyes("Head", 0, -.414, 1.005, .074, mat["primary"], .060) + cylinder("BodyGaugeRim", (0, -.402, .695), .117, .07, + mat["secondary"], vertices=12, rotation=(pi/2, 0, 0)) + cylinder("BodyGaugeFace", (0, -.444, .695), .085, .016, + mat["light"], vertices=12, rotation=(pi/2, 0, 0)) + beam("BodyGaugeNeedle", (0, -.458, .695), (.047, -.458, .747), + .012, mat["primary"], vertices=4) + if upgraded: + _slab("BodyChestArmor", (0, -.10, .82), (.81, .55, .61), + mat["primary"], .12) + # Face and gauge sit ahead of the armour, never buried inside it. + for side, s in (("L", -1), ("R", 1)): + cylinder("BodyPressureCylinder" + side, (s*.48, .06, 1.075), + .145, .54, mat["primary"], vertices=10) + cylinder("BodyPressureCap" + side, (s*.48, .06, 1.36), + .16, .07, mat["secondary"], vertices=10) + beam("BodyPressurePipe" + side, (s*.48, .13, .84), + (s*.30, .25, .66), .048, mat["accent"]) + box("HeadBrow", (0, -.37, 1.12), (.46, .17, .09), mat["light"]) + else: + cylinder("BodyChimney", (.235, .10, 1.245), .08, .23, + mat["accent"], vertices=8) + cylinder("BodyChimneyLip", (.235, .10, 1.365), .10, .045, + mat["secondary"], vertices=8) + + +def _boiler_arms(mat, upgraded): + for side, s in (("L", -1), ("R", 1)): + beam("Arm" + side + "Piston", (s*.33, .0, .88), + (s*.52, -.02, .63), .09, mat["accent"]) + _slab("Arm" + side + "Fist", (s*.53, -.11, .53), + (.29, .34, .28), mat["accent"], .045) + if upgraded and side == "L": + _slab("WeaponLPressureShield", (-.57, -.245, .75), + (.37, .20, .69), mat["primary"], .08) + _slab("WeaponLShieldStripe", (-.57, -.356, .75), + (.085, .025, .50), mat["secondary"], .025) + elif upgraded: + cylinder("WeaponRPistonCap", (.55, -.302, .59), .165, .08, + mat["secondary"], vertices=8, rotation=(pi/2, 0, 0)) + + +def _mist_legs(mat, tall=False, upgraded=False): + for side, s in (("L", -1), ("R", 1)): + hip = (s*.12, .045, .71 if tall else .48) + knee = (s*.25, .06 if side == "L" else -.04, .32) + ankle = (s*.20, -.12 if side == "L" else .02, .095) + beam("Leg" + side + "FoldUpper", hip, knee, + .10 if tall else .13, mat["primary"], vertices=5) + beam("Leg" + side + "FoldLower", knee, ankle, .075, + mat["secondary"], vertices=5) + _profile("Leg" + side + "TendrilFoot", + [(s*.20-.09,.035), (s*.20+.11,.035), + (s*.20+.07,.14), (s*.20-.045,.20)], + ankle[1]-.045, .20, mat["primary"]) + + +def _mist_mask(mat, z, large=False): + sx, sz = (.235, .29) if large else (.158, .218) + ellipsoid("HeadMistMask", (0, -.17, z), (sx, .105, sz), + mat["light"], subdivisions=2) + _eyes("Head", 0, -.273, z+.035, sx*.43, mat["accent"], sx*.42) + _profile("HeadMaskChin", [(-sx*.50,z-.10), (0,z-sz*.92), + (sx*.50,z-.10)], -.252, .022, mat["light"]) + + +def _dancer_body(mat, upgraded): + _profile("BodyFoldedRibbon", [(-.16,.56), (.10,.60), (.205,.97), + (.105,1.16), (-.06,1.13), (-.195,.86)], + .025, .27, mat["primary"]) + _profile("BodyVioletFold", [(-.145,.64), (-.04,.67), (.15,1.075), + (.05,1.12)], -.13, .038, mat["secondary"]) + _mist_mask(mat, 1.23) + if upgraded: + _crescent("HeadCrescentCrest", (0, .005, 1.37), .20, .065, + .08*pi, .92*pi, mat["secondary"], .075, 8) + _blade("BodyBackRibbonL", (-.12,.15,.94), .40, .13, -.9, + mat["secondary"], .06, -.05) + _blade("BodyBackRibbonR", (.12,.15,.94), .40, .13, .9, + mat["secondary"], .06, .05) + + +def _dancer_weapons(mat, upgraded): + if upgraded: + # One large open scissor: two distinct sweeping blades at one mint hub. + pivot = (.19, -.32, .79) + beam("ArmLUpper", (-.14,.015,1.05), (-.33,-.11,.85), + .065, mat["secondary"], vertices=5) + beam("ArmLForearm", (-.33,-.11,.85), pivot, + .061, mat["primary"], vertices=5) + beam("ArmRUpper", (.14,.015,1.05), (.36,-.12,.96), + .065, mat["primary"], vertices=5) + beam("ArmRForearm", (.36,-.12,.96), pivot, + .061, mat["secondary"], vertices=5) + _blade("WeaponScissorUpper", pivot, .69, .18, .57, + mat["light"], .075, .09) + _blade("WeaponScissorLower", (.19,-.405,.79), .66, .18, 1.42, + mat["light"], .075, .04) + ring("WeaponScissorHandleL", (.04,-.37,.655), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + ring("WeaponScissorHandleR", (-.005,-.37,.79), .09, .025, + mat["secondary"], rotation=(pi/2,0,0), segments=8) + cylinder("WeaponScissorMintPivot", (.19,-.463,.79), .087, .028, + mat["accent"], vertices=12, rotation=(pi/2,0,0)) + else: + for side, s, high in (("L", -1, False), ("R", 1, True)): + elbow = (s*.31, -.04, .91 if high else .80) + wrist = (s*.43, -.12, 1.07 if high else .66) + beam("Arm" + side + "Upper", (s*.14,.01,1.02), elbow, + .065, mat["primary"], vertices=5) + beam("Arm" + side + "Forearm", elbow, wrist, + .052, mat["secondary"], vertices=5) + _blade("Weapon" + side + "ThreadBlade", wrist, + .40, .065, s*(.50 if high else 2.12), + mat["light"], .045, s*.045) + cylinder("Weapon" + side + "MintGrip", wrist, .060, .09, + mat["accent"], vertices=8, rotation=(pi/2,0,0)) + + +def _mist_tank_body(mat, upgraded): + ellipsoid("BodyFoldedMist", (0,.035,.73), (.37,.25,.44), + mat["primary"], subdivisions=2) + _profile("BodyVioletCenterFold", [(-.22,.43), (.035,.39), + (.25,.90), (.04,1.09)], + -.205, .060, mat["secondary"]) + _mist_mask(mat, 1.145, large=True) + _crescent("BodyFrontCrescent", (0,-.32,.89), .44, .145, + .98*pi, 2.02*pi, mat["secondary"], .15, 12) + if upgraded: + _crescent("BodyOuterShield", (0,-.245,.99), .655, .17, + .89*pi, 2.11*pi, mat["light"], .15, 12) + _crescent("BodyRearShield", (0,.11,1.025), .60, .16, + .05*pi, .95*pi, mat["secondary"], .17, 12) + for side, s in (("L",-1),("R",1)): + _blade("BodyShieldWing" + side, (s*.44,.005,.72), + .49,.23,s*.39,mat["secondary"],.16,s*.10) + _blade("BodyShieldMintEdge" + side, (s*.49,-.09,.79), + .31,.047,s*.39,mat["accent"],.025,s*.065) + + +def _mist_tank_arms(mat, upgraded): + for side, s in (("L",-1),("R",1)): + beam("Arm" + side + "Fold", (s*.31,.005,.92), + (s*.43,-.045,.67), .080, mat["primary"], vertices=5) + _crescent("Arm" + side + "Crescent", (s*.42,-.14,.72), + .24,.075, -.4*pi if s < 0 else .6*pi, + .6*pi if s < 0 else 1.6*pi, + mat["secondary"],.095,8) + + +def _root_legs(mat, upgraded=False, four=False, spread=.32): + positions = [("L", -1, -.035), ("R", 1, -.035)] + if four: + positions = [("LFront",-1,-.27),("RFront",1,-.27), + ("LRear",-1,.28),("RRear",1,.28)] + for label, s, y in positions: + beam("Leg" + label + "Root", (s*spread*.65,y,.48), + (s*spread,y-.035,.13), .11 if four else .13, + mat["primary"], vertices=6) + _slab("Leg" + label + "Foot", (s*spread,y-.10,.075), + (.28,.36,.15), mat["primary"], .065) + # One broad toe root is stronger at gameplay scale than many twigs. + beam("Leg" + label + "Toe", (s*spread,y-.12,.095), + (s*spread+s*.06,y-.31,.055), .045, + mat["accent"], vertices=5) + + +def _leaf(name, origin, length, width, angle, mat, depth=.055): + x,y,z = origin + local = [(0,0),(width*.55,length*.44),(0,length), + (-width*.55,length*.44)] + points = [(x+u*cos(angle)+v*sin(angle), + z-u*sin(angle)+v*cos(angle)) for u,v in local] + return _profile(name,points,y,depth,mat) + + +def _thorn_body(mat, upgraded): + if upgraded: + ellipsoid("BodyCoiledRoot", (0,.08,.63), (.48,.34,.39), + mat["primary"],subdivisions=2) + ring("BodyRootCoil", (0,.065,.61), .365,.085, + mat["primary"],segments=10) + ellipsoid("HeadUpperJaw", (0,-.16,1.07), (.55,.34,.26), + mat["primary"],subdivisions=2) + _slab("HeadLowerJaw", (0,-.265,.66), (.87,.44,.22), + mat["primary"],.085) + _slab("HeadMouthDepth", (0,-.26,.84), (.78,.20,.28), + mat["secondary"],.08) + for i,x in enumerate((-.30,-.10,.10,.30)): + _profile("WeaponUpperFang%02d" % i, + [(x-.065,1.04),(x,.835),(x+.065,1.04)], + -.485,.055,mat["accent"]) + for i,x in enumerate((-.23,0,.23)): + _profile("WeaponLowerFang%02d" % i, + [(x-.07,.74),(x+.07,.74),(x,.91)], + -.497,.055,mat["accent"]) + for side,s in (("L",-1),("R",1)): + _leaf("HeadCheekLeaf" + side,(s*.40,-.29,.82),.39,.29, + s*.59,mat["secondary"],.11) + _leaf("HeadCrownLeaf" + side,(s*.15,.01,1.21),.23,.15, + s*.67,mat["accent"]) + _eyes("Head",0,-.425,1.155,.24,mat["accent"],.09) + else: + ellipsoid("BodyThornPod", (0,.03,.76), (.43,.34,.43), + mat["primary"],subdivisions=2) + _slab("HeadSlit",(0,-.308,.87),(.29,.045,.075),mat["secondary"],.025) + _eyes("Head",0,-.337,.96,.105,mat["accent"],.055) + for side,s in (("L",-1),("R",1)): + _leaf("HeadSprout" + side,(s*.10,.025,1.09),.31,.19, + s*.55,mat["secondary"],.07) + _blade("WeaponSideThorn" + side,(s*.34,.02,.76), + .24,.13,s*1.36,mat["secondary"],.13,s*.015) + for i,(x,y,z) in enumerate(((-.22,-.08,1.07),(.22,-.08,1.07), + (0,.285,.90))): + cone("BodyThorn%02d" % i,(x,y,z),.09,0,.25, + mat["accent"],vertices=5) + + +def _bark_head(mat, upgraded): + ellipsoid("HeadLowRoot", (0,-.36,.50), (.24,.23,.18), + mat["primary"]) + _eyes("Head",0,-.559,.54,.097,mat["accent"],.077) + if upgraded: + _slab("HeadBrowBark",(0,-.43,.68),(.55,.23,.14), + mat["primary"],.045) + + +def _bark_shell(mat, upgraded): + ellipsoid("BodyCorkShell", (0,.07,.80), (.57,.49,.49), + mat["primary"],subdivisions=2) + if upgraded: + # Three actual layered trunk cross sections, readable from above/front. + for index,(x,y,z,r) in enumerate(((0,-.345,.91,.42), + (-.42,.06,.99,.32), + (.42,.06,.99,.32))): + cylinder("BodyGrowthShield%02d" % index,(x,y,z),r,.17, + mat["primary"],vertices=12,rotation=(pi/2,0,0)) + for band,ratio in enumerate((.80,.50)): + ring("BodyGrowthRing%02d_%02d" % (index,band), + (x,y-.097,z),r*ratio,.022, + mat["accent"],rotation=(pi/2,0,0),segments=12) + cylinder("BodyGrowthHeart%02d" % index,(x,y-.099,z),r*.18,.02, + mat["secondary"],vertices=8,rotation=(pi/2,0,0)) + _leaf("BodyCrownLeafL",(-.09,.16,1.19),.25,.19,-.67, + mat["secondary"],.055) + _leaf("BodyCrownLeafR",(.09,.16,1.19),.25,.19,.67, + mat["accent"],.055) + else: + # Asymmetric overlapping cork plates make a turtle-like living shield. + for i,(x,y,z,w,h) in enumerate(((-.26,-.015,1.04,.39,.36), + (.18,-.07,1.11,.42,.31), + (0,.245,.93,.53,.39))): + _slab("BodyCorkPlate%02d" % i,(x,y,z),(w,.29,h), + mat["primary"],.08) + _leaf("BodyMossPlateL",(-.39,-.065,.87),.24,.20,-.49, + mat["secondary"],.08) + _leaf("BodyMossPlateR",(.31,.04,1.06),.20,.19,.57, + mat["secondary"],.06) + + +def _faction(spec): + faction = str(spec["faction"]).lower() + aliases = {"g":"glutpakt", "m":"nietenkonvent", "n":"nebelchor", + "w":"wurzelbund"} + return aliases.get(faction, faction) + + +def build_melee(spec, mat): + """Build a faction-specific melee unit or its visibly evolved upgrade.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _coal_body(mat, upgraded) + _coal_claws(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded, tall=True) + _shear_body(mat, upgraded) + _shear_weapons(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, tall=True, upgraded=upgraded) + _dancer_body(mat, upgraded) + _dancer_weapons(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=upgraded, spread=.34 if upgraded else .27) + _thorn_body(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht melee faction: " + faction) + + +def build_tank(spec, mat): + """Build a tank; upgrades add fortress tiers, pressure shields or growth rings.""" + faction = _faction(spec) + upgraded = bool(spec.get("upgraded", False)) + if faction == "glutpakt": + _stone_legs(mat, upgraded) + _basalt_body(mat, upgraded) + _basalt_arms(mat, upgraded) + elif faction == "nietenkonvent": + _machine_legs(mat, upgraded) + _boiler_body(mat, upgraded) + _boiler_arms(mat, upgraded) + elif faction == "nebelchor": + _mist_legs(mat, upgraded=upgraded) + _mist_tank_body(mat, upgraded) + _mist_tank_arms(mat, upgraded) + elif faction == "wurzelbund": + _root_legs(mat, upgraded, four=True, spread=.38 if upgraded else .33) + _bark_shell(mat, upgraded) + _bark_head(mat, upgraded) + else: + raise ValueError("Unknown Saumwacht tank faction: " + faction) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase4/standalone/create_worker.py b/assets-source/phase4/standalone/create_worker.py new file mode 100644 index 0000000..4752c97 --- /dev/null +++ b/assets-source/phase4/standalone/create_worker.py @@ -0,0 +1,3154 @@ +"""Saumwacht · Funkenleser · eigenständiges Blender-Python-Skript. + +In Blender: Scripting > Text > Open > diese Datei > Run Script. +Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert. +Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py. +Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs. +""" + +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = 'worker' # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {} # Beispiel: {'accent': 'D9A441'}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' + +# === VERFÜGBARE VARIANTEN =============================================== +ASSET_SPECS = [{'id': 'worker', + 'name': 'Funkenleser', + 'faction': 'neutral', + 'palette': 'worker', + 'role': 'worker', + 'upgraded': False, + 'height': 1.1, + 'footprint': 1.4, + 'file': 'worker.glb', + 'triangle_budget': 180000, + 'detail_level': 'high'}] + +def get_spec(asset_id): + for spec in ASSET_SPECS: + if spec["id"] == asset_id: + return dict(spec) + raise ValueError("Unbekannte ID für dieses Skript: " + asset_id) + +from math import pi +import re +import bpy +from mathutils import Vector + + +def _finish(obj, name, mat=None): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj.name = name + obj['part_name'] = name + if obj.type == 'MESH': + obj.data.name = name + '_Mesh' + for face in obj.data.polygons: + face.use_smooth = False + if mat is not None: + obj.data.materials.append(mat) + return obj + + +def box(name, loc, size, mat, rotation=None): + bpy.ops.mesh.primitive_cube_add(size=1, location=loc) + obj = bpy.context.object + obj.scale = size + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def ellipsoid(name, loc, scale, mat, subdivisions=1): + bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=subdivisions, radius=1, location=loc) + obj = bpy.context.object + obj.scale = scale + return _finish(obj, name, mat) + + +def cylinder(name, loc, radius, depth, mat, vertices=10, rotation=None): + return cone(name, loc, radius, radius, depth, mat, vertices, rotation) + + +def cone(name, loc, radius1, radius2, depth, mat, vertices=10, rotation=None): + bpy.ops.mesh.primitive_cone_add(vertices=vertices, radius1=radius1, + radius2=radius2, depth=depth, location=loc) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def beam(name, start, end, radius, mat, vertices=8): + start, end = Vector(start), Vector(end) + direction = end - start + if direction.length < 1e-6: + raise ValueError(name + ': beam endpoints must differ') + obj = cylinder(name, (start + end) * 0.5, radius, direction.length, mat, vertices) + obj.rotation_euler = direction.to_track_quat('Z', 'Y').to_euler() + return obj + + +def ring(name, loc, major_radius, minor_radius, mat, rotation=None, segments=12): + bpy.ops.mesh.primitive_torus_add(major_segments=segments, minor_segments=4, + location=loc, major_radius=major_radius, + minor_radius=minor_radius) + obj = bpy.context.object + if rotation is not None: + obj.rotation_euler = rotation + return _finish(obj, name, mat) + + +def mesh_object(name, vertices, faces, mat): + mesh = bpy.data.meshes.new(name + '_Mesh') + mesh.from_pydata(vertices, [], faces) + mesh.update() + obj = bpy.data.objects.new(name, mesh) + bpy.context.scene.collection.objects.link(obj) + return _finish(obj, name, mat) + + +def empty(name, loc=(0, 0, 0)): + name = re.sub(r'[^A-Za-z0-9_]', '_', name) + obj = bpy.data.objects.new(name, None) + obj['part_name'] = name + obj.location = loc + obj.empty_display_type = 'PLAIN_AXES' + obj.empty_display_size = 0.12 + bpy.context.scene.collection.objects.link(obj) + return obj + + +PALETTES = { + 'glutpakt': ['292B35', 'EF6B3B', 'D9A441', 'D8CEC0'], + 'nietenkonvent': ['247A80', 'C79A48', '657481', 'E6DCCA'], + 'nebelchor': ['45456F', '9578CF', '82DBCE', 'C4D6E5'], + 'wurzelbund': ['685441', '56845A', 'A7BA6C', 'D996AF'], + 'neutral': ['536375', 'A8654D', '9578CF', 'D8D2BF'], + 'worker': ['A8654D', '536375', 'D9A441', '82DBCE'], + 'terrain': ['657481', '292B35', 'D9A441', '56845A'], + 'team0': ['292B35', 'D9A441', '82DBCE', 'D8CEC0'], + 'team1': ['292B35', 'D9A441', 'E9967C', 'D8CEC0'], +} + + +def srgb_to_linear(value): + return value / 12.92 if value <= 0.04045 else ((value + 0.055) / 1.055) ** 2.4 + + +def make_materials(palette_name, overrides=None): + """Hex colours match Phase 3; shader inputs use linear RGB for glTF export. + + Override individual keys with RGB hex strings in an entry script, e.g. + PALETTE_OVERRIDES = {'accent': 'FFAA55'}. All materials stay opaque and matte. + """ + colours = dict(zip(('primary', 'secondary', 'accent', 'light'), PALETTES[palette_name])) + if palette_name == 'wurzelbund': + colours['water'] = '82DBCE' # Dew/spring accent from the Phase 3 healer icons. + colours['wood'] = '9B805C' + colours['bark_dark'] = '483A2F' + if palette_name in ('neutral', 'worker'): + colours['shadow'] = '202832' + if palette_name == 'neutral': + colours['rift'] = '82DBCE' + colours.update(overrides or {}) + result = {} + for key, hex_colour in colours.items(): + value = hex_colour.lstrip('#') + rgb = [srgb_to_linear(int(value[i:i + 2], 16) / 255) for i in (0, 2, 4)] + name = 'SW_' + palette_name + '_' + key + '_' + value + # A previous user-edited material must never be reset by another run. + mat = bpy.data.materials.new(name) + mat['material_name'] = name + mat.diffuse_color = (*rgb, 1) + mat.use_nodes = True + shader = mat.node_tree.nodes.get('Principled BSDF') + shader.inputs['Base Color'].default_value = (*rgb, 1) + shader.inputs['Metallic'].default_value = 0.08 if palette_name in ('nietenkonvent', 'team0', 'team1') else 0.0 + shader.inputs['Roughness'].default_value = 0.82 + if palette_name == 'glutpakt' and key == 'secondary': + shader.inputs['Emission Color'].default_value = (*rgb, 1) + shader.inputs['Emission Strength'].default_value = 0.18 + if palette_name == 'glutpakt' and key == 'accent': + shader.inputs['Metallic'].default_value = 0.5 + shader.inputs['Roughness'].default_value = 0.62 + result[key] = mat + return result + +from math import sin, cos, pi +from mathutils import Vector + + +def r_plate(name, loc, outline, depth, mat, bulge=.035): + """Solid X/Z silhouette with a faceted front and an editable local origin.""" + area = sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(outline, outline[1:]+outline[:1])) + if area < 0: + outline = list(reversed(outline)) + n = len(outline) + v = [(x,-depth/2,z) for x,z in outline] + [(x,depth/2,z) for x,z in outline] + v.append((sum(p[0] for p in outline)/n, -depth/2-bulge, sum(p[1] for p in outline)/n)) + f = [(2*n,i,(i+1)%n) for i in range(n)] + f.append(tuple(range(2*n-1,n-1,-1))) + f += [(i,i+n,(i+1)%n+n,(i+1)%n) for i in range(n)] + obj=mesh_object(name,v,f,mat) + obj.location=loc + return obj + + +def r_block(name, loc, size, mat, cut=.16): + w,d,h=size + x,z=w/2,h/2 + c=min(w,h)*cut + outline=[(-x+c,-z),(x-c,-z),(x,-z+c),(x,z-c), + (x-c,z),(-x+c,z),(-x,z-c),(-x,-z+c)] + return r_plate(name,loc,outline,d,mat,min(d*.10,.035)) + + +def r_rock(name, loc, size, mat, twist=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=1) + obj.rotation_euler=(.12+twist*.2,twist*.16,twist) + return obj + + +def r_sweep(name, points, radii, mat, sides=6, ribbon=False): + """A single bent solid, tapered to a true pole for claws/flames/roots.""" + vertices,loops,faces=[],[],[] + previous_u=None + for i,(pos,radius) in enumerate(zip(points,radii)): + pos=Vector(pos) + tangent=Vector(points[min(i+1,len(points)-1)])-Vector(points[max(i-1,0)]) + tangent.normalize() + if previous_u is None: + guide=Vector((0,1,0)) if ribbon else min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + if abs(tangent.dot(guide))>.98: + guide=Vector((1,0,0)) + u=tangent.cross(guide).normalized() + else: + u=(previous_u-tangent*previous_u.dot(tangent)).normalized() + if u.length<.001: + guide=min([Vector((1,0,0)),Vector((0,1,0)),Vector((0,0,1))],key=lambda v:abs(tangent.dot(v))) + u=tangent.cross(guide).normalized() + previous_u=u + v=tangent.cross(u) + if radius==0: + loops.append([len(vertices)]) + vertices.append(pos) + else: + loop=[] + for k in range(sides): + angle=2*pi*k/sides + loop.append(len(vertices)) + vertices.append(pos+radius*(u*cos(angle)+v*sin(angle)*(.22 if ribbon else 1))) + loops.append(loop) + if len(loops[0])>1: + faces.append(tuple(reversed(loops[0]))) + for lower,upper in zip(loops,loops[1:]): + for k in range(sides): + j=(k+1)%sides + if len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + elif len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + else: + # Curving rings do not make planar quads; give each triangle its own normal. + faces.extend([(lower[k],lower[j],upper[j]),(lower[k],upper[j],upper[k])]) + if len(loops[-1])>1: + faces.append(tuple(loops[-1])) + origin=Vector(points[0]) + obj=mesh_object(name,[p-origin for p in vertices],faces,mat) + obj.location=origin + return obj + + +def r_arch_shell(name, loc, profile, mat, segments=12): + """Solid rear 210-degree bell shell, with actual open front and closed cut edges.""" + area=sum(a[0]*b[1]-b[0]*a[1] for a,b in zip(profile,profile[1:]+profile[:1])) + if area<0: + profile=list(reversed(profile)) + verts=[] + for radius,z in profile: + for k in range(segments+1): + a=-pi/12+7*pi/6*k/segments + verts.append((radius*cos(a),radius*sin(a),z)) + n=segments+1 + faces=[] + for i in range(len(profile)): + j=(i+1)%len(profile) + for k in range(segments): + faces.append((i*n+k,i*n+k+1,j*n+k+1,j*n+k)) + faces.append(tuple(i*n for i in range(len(profile)))) + faces.append(tuple(i*n+segments for i in reversed(range(len(profile))))) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_lathe(name, loc, profile, mat, axis=(0,0,1), segments=12): + """Closed lathed profile; supports bowls, bells and their real inner walls.""" + w=Vector(axis).normalized() + guide=Vector((0,0,1)) if abs(w.z)<.9 else Vector((0,1,0)) + u=guide.cross(w).normalized() + v=w.cross(u) + verts,loops,faces=[],[],[] + for radius,z in profile: + loop=[] + for k in range(segments if radius else 1): + a=2*pi*k/segments + loop.append(len(verts)) + verts.append(w*z+radius*(u*cos(a)+v*sin(a))) + loops.append(loop) + for lower,upper in zip(loops,loops[1:]+loops[:1]): + if len(lower)==len(upper)==1: + continue + for k in range(segments): + j=(k+1)%segments + if len(lower)==1: + faces.append((lower[0],upper[j],upper[k])) + elif len(upper)==1: + faces.append((lower[k],lower[j],upper[0])) + else: + faces.append((lower[k],lower[j],upper[j],upper[k])) + obj=mesh_object(name,verts,faces,mat) + obj.location=loc + return obj + + +def r_band(name, start, end, radius, mat, sides=8): + return beam(name,start,end,radius,mat,vertices=sides) + + +def r_disc(name, loc, radius, depth, mat): + return cylinder(name,loc,radius,depth,mat,vertices=10,rotation=(pi/2,0,0)) + + +def r_inset(name, loc, outline, depth, rim, face): + """Raised face inset in a silhouette-shaped metal border.""" + r_plate(name+'_Rim',loc,outline,depth,rim) + r_plate(name+'_Face',(loc[0],loc[1]-depth*.55,loc[2]), + [(x*.82,z*.88) for x,z in outline],depth*.28,face) + + +def r_sun(name, loc, radius, m, rays=8): + x,y,z=loc + r_disc(name+'_Ring',loc,radius,.04,m['accent']) + r_disc(name+'_Face',(x,y-.027,z),radius*.72,.035,m['secondary']) + for k in range(rays): + a=2*pi*k/rays + r_sweep(name+'_Ray'+str(k),[(x+radius*.88*cos(a),y,z+radius*.88*sin(a)), + (x+radius*1.42*cos(a),y,z+radius*1.42*sin(a))], + [radius*.14,0],m['accent'],4) + +from math import pi, sin, cos +import hashlib +import random +import bpy +import bmesh +from mathutils import Matrix, Vector + + +def hd_finish(obj, width=.012, segments=3, smooth=False): + """Bake scale before bevel so round-overs have consistent physical width.""" + obj.data.transform(Matrix.Diagonal((*obj.scale, 1))) + obj.scale = (1,1,1) + bpy.context.view_layer.objects.active = obj + if width: + mod = obj.modifiers.new('Crafted_edge_radius','BEVEL') + mod.width = width + mod.segments = segments + mod.limit_method = 'ANGLE' + mod.angle_limit = .32 + mod.use_clamp_overlap = True + bpy.ops.object.modifier_apply(modifier=mod.name) + for face in obj.data.polygons: + face.use_smooth = smooth or len(face.vertices) == 4 + if width or smooth: + normal = obj.modifiers.new('Weighted_surface_normals','WEIGHTED_NORMAL') + normal.keep_sharp = True + normal.weight = 50 + bpy.ops.object.modifier_apply(modifier=normal.name) + return obj + + +def hd_box(name, loc, size, mat, radius=.012, rotation=None): + return hd_finish(box(name,loc,size,mat,rotation),radius) + + +def hd_plate(name,loc,outline,depth,mat,radius=.01,bulge=.0): + return hd_finish(r_plate(name,loc,outline,depth,mat,bulge),radius) + + +def hd_rock(name,loc,size,mat,seed=0): + obj=ellipsoid(name,loc,size,mat,subdivisions=2) + rng=random.Random(name+str(seed)) + # Separate broad chisel facets with chipped edges, not a smooth sphere. + for v in obj.data.vertices: + v.co *= rng.uniform(.94,1.045) + obj.rotation_euler=(.07*seed,.12*seed,.17*seed) + return hd_finish(obj,.009,2) + + +def hd_rod(name,a,b,radius,mat,sides=20): + return hd_finish(beam(name,a,b,radius,mat,sides),min(radius*.18,.007),2,True) + + +def hd_ring(name,loc,radius,thickness,mat,rotation=None,segments=40): + obj=ring(name,loc,radius,thickness,mat,rotation,segments) + for face in obj.data.polygons: face.use_smooth=True + return obj + + +def hd_disc(name,loc,radius,depth,mat): + return hd_finish(cylinder(name,loc,radius,depth,mat,32,(pi/2,0,0)),.006,3,True) + + +def hd_curve(name,points,radii,mat,sides=12,steps=5): + """Catmull-Rom centerline and tapered cross sections for claws and cables.""" + pts=[Vector(p) for p in points] + positions=[]; widths=[] + for i in range(len(pts)-1): + p0,p1,p2,p3=pts[max(0,i-1)],pts[i],pts[i+1],pts[min(len(pts)-1,i+2)] + for k in range(steps): + t=k/steps + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + positions.append(tuple(p)); widths.append(radii[i]*(1-t)+radii[i+1]*t) + positions.append(tuple(pts[-1]));widths.append(radii[-1]) + obj=r_sweep(name,positions,widths,mat,sides) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def hd_materials(m): + """A small shared PBR palette; values are linear RGB for glTF.""" + definitions={ + 'basalt':('41434B',.05,.77,0), 'edge':('62636A',.10,.71,0), + 'dark':('171A21',.15,.66,0), 'gold':('C99645',.78,.42,0), + 'gold_light':('F1CA7C',.68,.39,0), 'ember':('FF5210',.05,.40,1.25), + 'hot':('FFC65E',.0,.36,2.2), 'ceramic':('D8CDB2',.10,.37,0), + 'bone':('BAC8CF',.16,.55,0), 'rift':('CE609B',.10,.35,2.0), + } + for key,(hexcolor,metal,rough,emission) in definitions.items(): + name='SW_HD_'+key + mat=bpy.data.materials.new(name) + mat['material_name']=name + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1);mat.use_nodes=True + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=metal + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def hd_rivet(name,loc,m,r=.018): + hd_disc(name+'_Seat',loc,r*1.5,.009,m['dark']) + hd_disc(name+'_Head',(loc[0],loc[1]-.009,loc[2]),r,.018,m['gold_light']) + + +def hd_trim(name,points,m,r=.012): + return hd_curve(name,points,[r]*len(points),m['gold_light'],8,2) + + +def hd_sun(name,loc,r,m): + x,y,z=loc + hd_disc(name+'_Base',(x,y,z),r,.024,m['gold']) + hd_disc(name+'_Face',(x,y-.020,z),r*.68,.018,m['dark']) + hd_disc(name+'_Heart',(x,y-.033,z),r*.43,.022,m['gold_light']) + for i in range(12): + a=i*pi/6 + hd_plate(name+'_Ray'+str(i),(x,y-.032,z),[(r*.64*cos(a-.13),r*.64*sin(a-.13)), + (r*.96*cos(a),r*.96*sin(a)),(r*.64*cos(a+.13),r*.64*sin(a+.13))],.016,m['gold_light'],.002) + + +def hd_legs(m,spread=.30,height=.50,slim=False): + radius=.070 if slim else .13 + for s,side in [(-1,'L'),(1,'R')]: + n='Leg'+side + hip=(s*spread*.8,.055,height) + knee=(s*spread,.06,height*.53) + ankle=(s*spread,-.035,.13) + hd_rod(n+'_InnerThigh',hip,knee,radius*.64,m['dark']) + hd_rod(n+'_InnerShin',knee,ankle,radius*.64,m['dark']) + hd_rock(n+'_ThighArmor',tuple((Vector(hip)+Vector(knee))*.5),(radius*1.24,radius*.90,height*.24),m['basalt'],s) + hd_rock(n+'_ShinArmor',tuple((Vector(knee)+Vector(ankle))*.5),(radius*1.10,radius,height*.22),m['basalt'],2*s) + for p,label in [(hip,'Hip'),(knee,'Knee'),(ankle,'Ankle')]: + hd_disc(n+'_'+label+'Pivot',(p[0],p[1]-radius*.8,p[2]),radius*.72,.055,m['gold']) + hd_disc(n+'_'+label+'Pin',(p[0],p[1]-radius*1.12,p[2]),radius*.36,.022,m['dark']) + hd_disc(n+'_'+label+'Rim',(p[0],p[1]-radius*1.27,p[2]),radius*.16,.025,m['gold_light']) + # Three individually modeled tapered foot/toe plates. + for j in range(3): + x=ankle[0]+(j-1)*radius*.70 + toe=[(-radius*.40,-.045),(radius*.40,-.045),(radius*.30,.060),(0,.090),(-radius*.32,.060)] + hd_plate(n+'_Toe'+str(j),(x,-.135,.065),toe,.26 if not slim else .20,m['basalt'],.013) + hd_box(n+'_ToeCap'+str(j),(x,-.225,.075),(radius*.62,.045,.048),m['gold'],.008) + hd_box(n+'_AnkleCuff',(ankle[0],-.05,.19),(radius*2.65,.22,.065),m['gold'],.012) + if not slim: + hd_plate(n+'_KneeGuard',(knee[0],-.103,knee[2]),[(-.10,.09),(.10,.09),(.085,-.08),(0,-.15),(-.085,-.08)],.075,m['edge'],.014) + else: + hd_plate(n+'_ShinGold',(knee[0],-.095,knee[2]-.10),[(-.057,.14),(.057,.14),(.026,-.11),(0,-.21)],.046,m['gold'],.005) + hd_plate(n+'_ShinEmber',(knee[0],-.126,knee[2]-.11),[(-.018,.08),(.018,.08),(0,-.14)],.015,m['ember'],.002) + + +def hd_arm(name,shoulder,elbow,hand,m,radius=.16,fingers=True): + hd_rod(name+'_UpperCore',shoulder,elbow,radius*.56,m['dark']) + hd_rod(name+'_ForearmCore',elbow,hand,radius*.64,m['dark']) + hd_rock(name+'_Elbow',elbow,(radius*.90,)*3,m['basalt'],2) + hd_rock(name+'_UpperArmor',tuple((Vector(shoulder)+Vector(elbow))*.5),(radius*1.08,radius*.88,Vector(shoulder).lerp(Vector(elbow),.5).z*.17),m['basalt'],1) + hd_rock(name+'_ForearmArmor',tuple((Vector(elbow)+Vector(hand))*.5),(radius*1.20,radius,Vector(elbow).lerp(Vector(hand),.5).z*.28),m['basalt'],3) + hd_rock(name+'_Shoulder',shoulder,(radius*1.48,radius*1.24,radius*1.15),m['basalt'],2) + hd_disc(name+'_ShoulderJoint',(shoulder[0],shoulder[1]-radius*.85,shoulder[2]),radius*.66,.052,m['gold']) + for t,label in [(.58,'UpperBand'),(.85,'WristBand')]: + p=Vector(elbow).lerp(Vector(hand),t) + d=(Vector(hand)-Vector(elbow)).normalized()*.040 + hd_rod(name+'_'+label,tuple(p-d),tuple(p+d),radius*1.27,m['gold'],24) + hd_rivet(name+'_'+label+'Rivet',(p.x,p.y-radius*1.25,p.z),m) + hd_rock(name+'_Palm',hand,(radius*1.15,radius*.81,radius*1.06),m['basalt'],4) + if fingers: + for j in range(4): + x=hand[0]+(j-1.5)*radius*.46 + for k in range(2): + hd_box(name+'_Finger%d_%d'%(j,k),(x,hand[1]-.09-k*.04,hand[2]-.045-k*.07), + (radius*.40,radius*.53,radius*.55),m['edge'] if k==0 else m['basalt'],radius*.08) + s=-1 if hand[0]<0 else 1 + hd_rock(name+'_Thumb',(hand[0]-s*radius,hand[1]-.025,hand[2]-.04),(radius*.46,radius*.62,radius*.76),m['basalt'],1) + + +def hd_tower(name,loc,size,m): + x,y,z=loc;w,d,h=size + hd_box(name+'_StoneKeep',(x,y,z),(w,d,h),m['basalt'],.018) + hd_box(name+'_LowerCornice',(x,y,z-h*.31),(w*1.04,d*1.04,.045),m['gold'],.008) + hd_box(name+'_UpperCornice',(x,y,z+h*.34),(w*1.055,d*1.055,.045),m['edge'],.008) + for j in range(3): + px=x+(j-1)*w*.26 + hd_box(name+'_WindowRecess'+str(j),(px,y-d*.5-.014,z),(w*.12,.018,h*.42),m['dark'],.006) + hd_box(name+'_WindowFire'+str(j),(px,y-d*.5-.026,z),(w*.052,.009,h*.30),m['ember'],.003) + hd_box(name+'_WindowLintel'+str(j),(px,y-d*.5-.020,z+h*.25),(w*.19,.07,.028),m['edge'],.003) + for k,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + hd_box(name+'_Merlon'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.55),(w*.29,d*.31,h*.29),m['basalt'],.010) + hd_box(name+'_MerlonCap'+str(k),(x+dx*w*.35,y+dy*d*.34,z+h*.70),(w*.31,d*.33,.032),m['edge'],.004) + + +def hd_tank(up,m): + hd_legs(m,.295,.46) + hd_rock('Body_ArmoredCore',(0,.04,.82),(.42,.31,.48),m['dark'],1) + # Broad tapered chest formed from five slabs, with a narrow recessed furnace. + for s,side in [(-1,'L'),(1,'R')]: + outline=[(s*.045,.45),(s*.34,.40),(s*.41,.20),(s*.34,-.27),(s*.05,-.46)] + hd_plate('Body_Chest'+side,(0,-.28,.84),outline,.22,m['basalt'],.020,.018) + chest_pieces=[[(.078,.40),(.28,.365),(.335,.21),(.18,.075),(.083,.17)], + [(.19,.045),(.337,.17),(.298,-.12),(.21,-.18),(.067,-.052),(.087,.125)], + [(.070,-.094),(.215,-.217),(.286,-.162),(.222,-.30),(.068,-.385)]] + for j,outline_piece in enumerate(chest_pieces): + hd_plate('Body_ChestRelief'+side+str(j),(0,-.411-j*.006,.84),[(s*x,z) for x,z in outline_piece],.066,m['basalt'] if j%2 else m['edge'],.007,.021) + hd_trim('Body_Border'+side,[(s*.05,-.437,.40),(s*.36,-.407,.62),(s*.40,-.385,1.17),(s*.27,-.394,1.28)],m,.021) + # Chisel seams divide the armor into larger readable stone layers. + hd_curve('Body_Seam'+side,[(s*.065,-.418,.72),(s*.18,-.410,.87),(s*.12,-.409,1.01),(s*.32,-.404,1.14)],[.009]*4,m['dark'],6,1) + hd_arm('Arm'+side,(s*.49,.0,1.04),(s*.62,-.01,.76),(s*.65,-.14,.46),m,.155) + hd_plate('Arm'+side+'_Pauldron',(s*.48,-.105,1.12),[(-.21,.05),(-.13,.17),(.13,.17),(.21,.04),(.15,-.15),(-.15,-.15)],.34,m['gold'],.016) + hd_plate('Arm'+side+'_PauldronStone',(s*.48,-.139,1.16),[(-.17,.03),(-.10,.14),(.10,.14),(.17,.03),(.11,-.10),(-.11,-.10)],.33,m['basalt'],.014) + if up: + hd_tower('Arm'+side+'_Castle',(s*.48,.01,1.31),(.38,.40,.29),m) + hd_tower('Arm'+side+'_Bastion',(s*.65,-.08,.68),(.29,.32,.24),m) + for z in [.59,1.19]: + hd_rivet('Body_'+side+'Fastener'+str(z),(s*.31,-.414,z),m,.023) + hd_box('Head_FurnaceRecess',(0,-.402,1.09),(.095,.055,.32),m['dark'],.007) + hd_box('Head_Fire',(0,-.432,1.10),(.039,.025,.258),m['ember'],.008) + hd_box('Head_FireHeart',(0,-.446,1.10),(.012,.005,.19),m['hot'],.002) + for s in [-1,1]: + hd_box('Body_CenterGold'+str(s),(s*.061,-.44,1.02),(.023,.034,.51),m['gold'],.006) + hd_plate('Body_BottomGold',(0,-.443,.70),[(-.072,.05),(.072,.05),(0,-.13)],.030,m['gold'],.005) + if up: + hd_tower('Head_Crown',(0,.01,1.46),(.28,.31,.31),m) + hd_box('Body_SpineGold',(0,-.446,.61),(.025,.040,.26),m['gold'],.005) + + +def hd_coal(up,m): + hd_legs(m,.25,.39) + hd_rock('Body_LavaCore',(0,.025,.76),(.375,.27,.39),m['ember'],2) + # Interlocking shell plates leave true gaps above an orange inner body. + for j,z in enumerate([.53,.81,1.07]): + for k in range(7): + a=2*pi*k/7+.20*(j%2) + if sin(a)<-.42:continue + pos=(.33*cos(a),.24*sin(a),z) + hd_rock('Body_Shell%d_%d'%(j,k),pos,(.19,.135,.205),m['basalt'],j*3+k) + hd_rock('Head_JawCavity',(0,-.245,.77),(.37,.15,.235),m['dark'],0) + hd_plate('Head_MouthEmber',(0,-.345,.78),[(-.30,.07),(-.17,.10),(0,.02),(.17,.10),(.30,.07),(.24,-.08),(0,-.15),(-.24,-.08)],.028,m['ember'],.008) + for s,side in [(-1,'L'),(1,'R')]: + hd_rock('Head_Brow'+side,(s*.19,-.26,1.025),(.22,.17,.145),m['basalt'],s*2) + hd_curve('Head_Eye'+side,[(s*.29,-.419,1.02),(s*.18,-.433,.99),(s*.09,-.413,.97)],[.012,.019,.007],m['hot'],8,3) + hd_rock('Head_Cheek'+side,(s*.32,-.24,.82),(.15,.13,.22),m['basalt'],4*s) + for j in range(4): + x=s*(.035+j*.07) + hd_curve('Head_UpperTooth'+side+str(j),[(x,-.32,.96-j*.016),(x,-.405,.85-j*.016),(x-s*.010,-.413,.80-j*.012)],[.055,.029,0],m['edge'],8,3) + hd_curve('Head_LowerTooth'+side+str(j),[(x,-.28,.54+j*.02),(x,-.38,.67+j*.01),(x,-.40,.72+j*.01)],[.057,.027,0],m['basalt'],8,3) + hd_arm('Arm'+side,(s*.44,.03,.98),(s*.54,-.015,.72),(s*.57,-.16,.52),m,.14,False) + for j in range(3): + x=s*.58+(j-1)*.14 + hd_curve('Weapon'+side+'_Claw'+str(j),[(x,-.20,.60),(x+s*.035,-.37,.48),(x+s*.01,-.48,.26),(x-s*.070,-.41,.18)], + [.10 if up else .075,.095 if up else .068,.045,0],m['gold'],16,6) + hd_rivet('Arm'+side+'_Knuckle'+str(j),(x,-.27,.63),m,.021) + hd_plate('Arm'+side+'_ShoulderTrim',(s*.42,-.125,1.085),[(-.10,.04),(.10,.04),(.08,-.08),(0,-.12),(-.08,-.08)],.04,m['gold'],.008) + for k in range(5 if up else 3): + x=(k-(2 if up else 1))*.15 + hd_curve('Body_DorsalSpine'+str(k),[(x,.12,1.02),(x*1.12,.13,1.26+(.10 if k%2==0 else 0)),(x*.95,.10,1.43 if up else 1.32)], [.125,.085,0],m['basalt'],9,3) + hd_rock('Head_Chin',(0,-.20,.53),(.24,.19,.12),m['basalt'],5) + + +def hd_lancer(m): + hd_legs(m,.23,.74,True) + hd_rod('Body_Spine',(0,.045,.61),(0,.03,1.24),.085,m['dark']) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Cuirass'+side,(0,-.025,1.07),[(s*.025,.17),(s*.23,.13),(s*.16,-.13),(s*.025,-.22)],.20,m['gold'],.011) + hd_plate('Body_ChestStone'+side,(0,-.071,1.08),[(s*.048,.13),(s*.18,.10),(s*.12,-.10),(s*.048,-.15)],.16,m['basalt'],.008) + hd_arm('Arm'+side,(s*.24,.01,1.21),(s*.33,-.02,1.03),(s*.30,-.23,.96),m,.065) + hd_plate('Arm'+side+'_ShoulderFin',(s*.28,0,1.23),[(s*-.07,-.07),(s*.20,-.035),(s*.03,.16)],.15,m['gold'],.007) + hd_plate('Body_EmberHeart',(0,-.162,1.03),[(-.028,.10),(.028,.10),(0,-.13)],.019,m['ember'],.003) + hd_rod('Head_Neck',(0,.03,1.21),(0,.03,1.37),.06,m['dark']) + hd_plate('Head_Helmet',(0,-.01,1.47),[(-.19,.105),(0,-.005),(.19,.105),(.072,-.09),(0,-.21),(-.072,-.09)],.22,m['gold'],.008) + hd_plate('Head_Visor',(0,-.135,1.40),[(-.052,.018),(.052,.018),(0,-.116)],.017,m['ember'],.003) + hd_curve('Head_Crest',[(0,.07,1.49),(0,.12,1.64),(-.06,.11,1.76)],[.061,.034,0],m['gold_light'],10,4) + a=Vector((-.71,-.265,1.01)); b=Vector((.70,-.29,.94)) + hd_rod('Weapon_LanceShaft',a,b,.046,m['dark'],24) + hd_rod('Weapon_LanceEmber',a+Vector((0,-.042,0)),b+Vector((0,-.042,0)),.011,m['ember'],10) + for k in range(11): + t=.05+k*.087;p=a.lerp(b,t) + hd_rod('Weapon_LanceCollar'+str(k),p-Vector((.012,0,0)),p+Vector((.012,0,0)),.065,m['gold'],24) + hd_curve('Weapon_SpearHead',[b,b+Vector((.14,0,-.005)),b+Vector((.46,0,-.02))],[.06,.092,0],m['ember'],8,3) + for s in [-1,1]: + hd_curve('Weapon_SpearEdge'+str(s),[b+Vector((0,0,s*.07)),b+Vector((.17,0,s*.085)),b+Vector((.47,0,-.02))],[.024,.020,0],m['gold_light'],8,3) + + +def hd_ballista(m): + hd_legs(m,.33,.62) + hd_box('Body_Gearbox',(0,.02,.66),(.49,.43,.26),m['basalt'],.035) + for s,side in [(-1,'L'),(1,'R')]: + hd_disc('Body_Crank'+side,(s*.23,-.21,.73),.16,.055,m['gold']) + hd_disc('Body_CrankInset'+side,(s*.23,-.247,.73),.10,.018,m['dark']) + for k in range(8): + a=k*pi/4 + hd_box('Body_CrankTooth'+side+str(k),(s*.23+.137*cos(a),-.212,.73+.137*sin(a)),(.055,.067,.052),m['gold'],.006,rotation=(0,a,0)) + hd_box('Weapon_Rail'+side,(s*.13,-.11,.99),(.095,1.15,.14),m['basalt'],.018) + hd_box('Weapon_RailTrim'+side,(s*.13,-.11,1.068),(.052,1.17,.020),m['gold'],.005) + bow=[(s*.11,-.46,1.00),(s*.39,-.47,.97),(s*.67,-.31,1.01),(s*.80,.045,1.12)] + hd_curve('Weapon_GlassLimb'+side,bow,[.095,.12,.095,.051],m['ember'],12,7) + hd_curve('Weapon_LimbEdge'+side,[(x,y,z+.068) for x,y,z in bow],[.022,.025,.022,.017],m['gold'],10,7) + hd_curve('Weapon_DrawCable'+side,[bow[-1],(s*.37,.26,1.09),(0,.45,1.075)],[.011,.011,.011],m['dark'],10,3) + hd_rod('Weapon_LimbClamp'+side,(s*.18,-.52,.95),(s*.18,-.39,1.055),.089,m['gold'],12) + hd_box('Weapon_RearHousing',(0,.46,1.06),(.38,.25,.29),m['basalt'],.023) + hd_box('Weapon_RearTrim',(0,.40,1.08),(.42,.055,.33),m['gold'],.012) + hd_rod('Weapon_CentralBolt',(0,.38,1.085),(0,-.70,1.085),.035,m['ember'],16) + hd_curve('Weapon_BoltHead',[(0,-.62,1.085),(0,-.76,1.085),(0,-1.00,1.085)],[.040,.085,0],m['ember'],8,3) + for k in range(6): + hd_box('Weapon_RailRivet'+str(k),(.17,-.54+k*.18,1.10),(.025,.025,.026),m['gold_light'],.005) + + +def hd_mortar(up,m): + hd_legs(m,.29,.42) + hd_rock('Body_LowerCore',(0,.035,.60),(.38,.28,.25),m['basalt'],3) + radius=.49 if up else .435 + # Closed outer/inner profile: deep bore with individual radial barrel staves. + profile=[(0,0),(.22,.025),(radius*.83,.24),(radius,.64),(radius*.85,.68),(radius*.74,.60),(radius*.48,.16),(0,.14)] + obj=r_lathe('Body_MortarBore',(0,.07,.51),profile,m['dark'],segments=48) + hd_finish(obj,.006,2,True) + for k in range(12): + a=2*pi*k/12 + x=radius*.80*cos(a);y=.07+radius*.80*sin(a) + o=hd_rock('Body_MortarStave'+str(k),(x,y,.86),(.15,.13,.29),m['basalt'],k) + o.rotation_euler[2]=a + p=(radius*.98*cos(a),.07+radius*.98*sin(a),1.125) + hd_box('Body_RimClasp'+str(k),p,(.115,.13,.15),m['gold'],.014,rotation=(0,0,a-pi/2)) + hd_ring('Body_MortarLip',(0,.07,1.175),radius*.91,.033,m['gold_light'],segments=64) + hd_ring('Body_MortarBelt',(0,.07,.68),radius*.72,.027,m['gold'],segments=48) + pool_z=1.015 if up else .79 + hd_finish(cylinder('Weapon_LavaPool',(0,.07,pool_z),radius*.68,.038,m['ember'],48),.005,2,True) + if not up: + hd_rock('Weapon_EmberBoulder',(0,.02,.87),(.18,.18,.17),m['ember'],1) + for k in range(7): + a=k*2*pi/7 + hd_rock('Weapon_BoulderCrust'+str(k),(.14*cos(a),.02+.14*sin(a),.89),(.074,.068,.10),m['basalt'],k) + else: + for k in range(3): + hd_curve('Weapon_LavaEddy'+str(k),[(.26*cos(a+k),.07+.26*sin(a+k),pool_z+.026) for a in [0,.6,1.1,1.8,2.4]], [.009]*5,m['hot'],8,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.46,.055,.99),(s*.59,-.04,.73),(s*.43,-.29,.52),m,.155) + hd_plate('Body_FrontBadge',(0,-.355,.83),[(-.15,.17),(.15,.17),(.11,-.12),(0,-.25),(-.11,-.12)],.060,m['gold'],.009) + hd_plate('Body_FrontBadgeStone',(0,-.397,.84),[(-.10,.13),(.10,.13),(.070,-.10),(0,-.18),(-.070,-.10)],.029,m['basalt'],.006) + hd_plate('Body_FrontSigil',(0,-.42,.83),[(-.024,.09),(.025,.12),(.037,-.065),(0,-.14),(-.036,-.065)],.018,m['ember'],.003) + + +def hd_hearth(up,m): + hd_legs(m,.28,.45) + hd_rock('Body_HearthBack',(0,.13,.88),(.43,.32,.44),m['basalt'],1) + # Deep oven vault: an open front arch with a visible brick-lined interior. + hd_plate('Body_OvenDark',(0,-.20,.99),[(-.30,-.25),(-.30,.10),(-.20,.27),(0,.35),(.20,.27),(.30,.10),(.30,-.25)],.085,m['dark'],.016) + if not up: + for j in range(3): + for k in range(3): + hd_box('Body_HearthBrick%d_%d'%(j,k),((k-1)*.15,-.251,.83+j*.10),(.136,.024,.083),m['basalt'],.009) + for k in range(3): + x=(k-1)*.12 + hd_curve('Flame_Oven'+str(k),[(x,-.29,.79),(x+.04,-.30,.93),(x-.015,-.30,1.06+(k%2)*.15)], [.068,.058,0],m['ember'],12,6) + for k in range(11): + a=pi*k/10 + hd_box('Body_ArchStone'+str(k),(.335*cos(a),-.16,1.03+.335*sin(a)),(.125,.25,.19),m['ceramic'],.018,rotation=(0,pi/2-a,0)) + for s in [-1,1]: + for j in range(2): + hd_box('Body_Pillar%d_%d'%(s,j),(s*.335,-.16,.85+j*.14),(.15,.25,.13),m['ceramic'],.015) + hd_box('Head_Chimney',(0,.045,1.42),(.35,.31,.25),m['ceramic'],.029) + hd_box('Head_ChimneyRecess',(0,-.119,1.41),(.21,.015,.10),m['dark'],.012) + hd_box('Head_ChimneyCap',(0,.04,1.56),(.40,.35,.07),m['ceramic'],.017) + else: + hd_disc('Body_SunSocket',(0,-.30,1.22),.25,.06,m['dark']) + hd_ring('Body_SunFrame',(0,-.36,1.22),.248,.042,m['gold'],(pi/2,0,0),64) + hd_rock('Body_SunHeart',(0,-.34,1.22),(.203,.092,.203),m['ember'],0) + for j in range(3): + points=[] + for k in range(10): + a=k*.30+j*2*pi/3 + r=.018+k*.017 + points.append((r*cos(a),-.443+.025*(r/.18)**2,1.22+r*sin(a))) + hd_curve('Flame_SolarEddy'+str(j),points,[.006]*10,m['hot'],8,3) + for k in range(9): + a=pi*k/8 + hd_curve('Body_HaloRay'+str(k),[(.30*cos(a),-.13,1.22+.30*sin(a)),(.44*cos(a),-.13,1.22+.44*sin(a))],[.045,0],m['gold'],10,3) + for s,side in [(-1,'L'),(1,'R')]: + hd_plate('Body_Mantle'+side,(s*.40,.07,.99),[(s*-.06,.40),(s*.15,.32),(s*.19,-.24),(s*.10,-.35),(s*-.13,-.20)],.27,m['ceramic'],.020) + hd_sun('Body_MantleSun'+side,(s*.43,-.085,1.19),.082,m) + hd_plate('Body_Tabard'+side,(s*.40,-.16,.46),[(-.10,.20),(.10,.20),(.105,-.22),(0,-.32),(-.105,-.22)],.045,m['ceramic'],.011) + hd_sun('Body_TabardSun'+side,(s*.40,-.19,.42),.060,m) + r=.36 if up else .30 + obj=r_lathe('Weapon_HearthBowl',(0,-.40,.54),[(0,0),(.15,.02),(r,.16),(r*1.04,.22),(r*.88,.23),(r*.81,.18),(.16,.06),(0,.06)],m['gold'],segments=48) + hd_finish(obj,.009,3,True) + hd_ring('Weapon_BowlRim',(0,-.40,.762),r*.97,.022,m['gold_light'],segments=48) + hd_finish(cylinder('Weapon_EmberBed',(0,-.40,.697),r*.79,.023,m['ember'],40),.005,2,True) + for k in range(5): + x=(k-2)*.085;h=.19+(.15 if k==2 else .06*(k%2)) + hd_curve('Weapon_Flame'+str(k),[(x,-.40,.70),(x-.035,-.38,.70+h*.35),(x+.035,-.38,.70+h*.72),(x-.02,-.38,.70+h)], [.050,.049,.023,0],m['hot'] if k%2 else m['ember'],12,6) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.42,.02,1.05),(s*.55,-.16,.80),(s*.34,-.41,.65),m,.15) + hd_sun('Arm'+side+'_Seal',(s*.45,-.155,1.06),.095,m) + hd_sun('Weapon_BowlSeal',(0,-.702,.65),.063,m) + if up: + hd_curve('Body_SolarStream',[(0,-.44,1.11),(.05,-.45,.98),(-.03,-.43,.83),(0,-.43,.72)],[.023,.024,.016,.013],m['hot'],12,6) + + +def build_high_glutpakt(spec,m): + hd_materials(m) + role=spec['role'];up=spec['upgraded'] + if role=='melee':hd_coal(up,m) + elif role=='tank':hd_tank(up,m) + elif role=='ranged':hd_ballista(m) if up else hd_lancer(m) + elif role=='artillery':hd_mortar(up,m) + elif role=='support':hd_hearth(up,m) + + +def build_high_enemy(spec,m): + hd_materials(m) + id=spec['id'] + if id in ('e05','e06','e09','e10'): + build_expedition_enemy(id,m) + return + if id in ('e01','e02'): + heavy=id=='e02' + hd_rock('Body_Core',(0,0,.52),(.44,.55,.30),m['dark'],2) + # Segmented back carapace, raised central ridge and six clawed legs. + for j in range(4): + y=-.34+j*.25 + width=.46 if heavy else .40 + hd_plate('Body_Carapace'+str(j),(0,y,.62),[(-width,0),(-width*.67,.23),(0,.35),(width*.67,.23),(width,0),(0,-.09)],.26,m['bone'] if j%2 else m['basalt'],.024) + hd_curve('Body_SeamGlow'+str(j),[(-width*.69,y-.145,.83),(0,y-.147,.95),(width*.69,y-.145,.83)],[.012,.015,.012],m['rift'],8,2) + if heavy: + hd_curve('Body_Spine'+str(j),[(0,y,.94),(0,y+.06,1.15),(0,y+.13,1.28)],[.10,.055,0],m['bone'],12,5) + hd_rock('Head_Skull',(0,-.65,.54),(.29,.20,.19),m['basalt'],3) + for s,side in [(-1,'L'),(1,'R')]: + for k in range(3): + y=-.38+k*.35;n='Leg'+side+str(k) + hip=(s*.30,y,.53);knee=(s*.61,y-.11,.36);foot=(s*.77,y-.27,.06) + hd_rod(n+'_Upper',hip,knee,.070 if heavy else .054,m['basalt']) + hd_rock(n+'_Joint',knee,(.085,)*3,m['bone'],k) + hd_curve(n+'_Shin',[knee,(s*.75,y-.20,.20),foot],[.076,.045,0],m['bone'],12,4) + hd_rod(n+'_Inset',tuple(Vector(hip)+Vector((0,-.04,.035))),tuple(Vector(knee)+Vector((0,-.04,.035))),.014,m['rift'],8) + hd_rock('Head_Eye'+side,(s*.115,-.816,.60),(.055,.021,.036),m['rift'],0) + hd_curve('Head_Mandible'+side,[(s*.19,-.74,.45),(s*.29,-.91,.40),(s*.17,-1.00,.44)],[.070,.046,0],m['bone'],12,6) + elif id=='e07': + hd_rock('Body_DeerCore',(0,.12,1.12),(.38,.62,.42),m['dark'],1) + for j in range(5): + y=-.38+j*.22 + hd_rock('Body_BackArmor'+str(j),(0,y,1.37),(.40,.19,.21),m['basalt'],j) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.35,.57]): + n='Leg'+side+str(j) + hip=(s*.27,y,1.08); knee=(s*.36,y+.10,.60); foot=(s*.36,y-.02,.08) + hd_rod(n+'_Upper',hip,knee,.082,m['dark']) + hd_rock(n+'_Knee',knee,(.12,.13,.14),m['basalt'],s) + hd_rod(n+'_Shin',knee,foot,.060,m['bone']) + hd_box(n+'_Hoof',(foot[0],foot[1]-.04,.10),(.19,.27,.20),m['dark'],.025) + hd_box(n+'_ClovenLine',(foot[0],foot[1]-.179,.105),(.018,.012,.16),m['rift'],.004) + for j in range(4): + hd_curve('Body_Rib'+side+str(j),[(s*.12,-.16+j*.16,1.43),(s*.35,-.14+j*.16,1.26),(s*.32,-.13+j*.16,.99)],[.065,.074,.037],m['bone'],10,3) + hd_curve('Head_Antler'+side,[(s*.17,-.39,1.89),(s*.36,-.25,2.17),(s*.56,-.10,2.42),(s*.50,.05,2.61)],[.075,.065,.036,0],m['bone'],12,7) + for k in range(3): + z=2.05+k*.14;x=s*(.28+k*.13);y=-.30+k*.09 + hd_curve('Head_AntlerProng'+side+str(k),[(x,y,z),(x+s*.19,y-.05,z+.15),(x+s*.20,y-.13,z+.28)],[.041,.028,0],m['bone'],10,5) + hd_rock('Head_Eye'+side,(s*.155,-.77,1.82),(.060,.041,.039),m['rift'],0) + hd_rock('Head_Neck',(0,-.36,1.54),(.23,.26,.37),m['basalt'],2) + hd_rock('Head_Skull',(0,-.58,1.79),(.25,.24,.25),m['bone'],4) + hd_rock('Head_Muzzle',(0,-.81,1.69),(.16,.24,.13),m['bone'],3) + hd_box('Head_Nose',(0,-1.01,1.69),(.21,.055,.12),m['dark'],.022) + hd_curve('Body_Tail',[(0,.70,1.20),(0,.89,1.05),(0,.95,.88)],[.075,.053,0],m['bone'],10,5) + else: + colossus=id=='e08'; ghost=id=='e03' + if colossus: + # A stone portcullis knight, with layered breastplates and battlements. + mm=dict(m);mm['gold']=m['bone'];mm['gold_light']=m['bone'];mm['ember']=m['rift'];mm['hot']=m['rift'] + hd_tank(True,mm) + for s in [-1,1]: + hd_curve('Body_RiftHorn'+str(s),[(s*.30,.06,1.48),(s*.40,.03,1.73),(s*.25,.04,1.86)],[.095,.066,0],m['bone'],12,5) + return + hd_rock('Body_Torso',(0,.025,1.08),(.24,.17,.34),m['dark'],2) + for j in range(5): + z=.93+j*.09 + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Body_Rib'+side+str(j),[(s*.04,-.12,z),(s*.20,-.12,z+.03),(s*.23,.025,z+.01)],[.025,.033,.022],m['bone'],10,3) + hd_rock('Head_Skull',(0,-.005,1.63),(.20,.145,.24),m['bone'],1) + hd_plate('Head_Face',(0,-.16,1.59),[(-.14,.08),(.14,.08),(.10,-.12),(0,-.18),(-.10,-.12)],.045,m['dark'],.012) + for s,side in [(-1,'L'),(1,'R')]: + hd_curve('Head_Eye'+side,[(s*.035,-.20,1.65),(s*.12,-.20,1.68)],[.020,.015],m['rift'],8,2) + hd_arm('Arm'+side,(s*.24,.0,1.29),(s*.38,-.09,1.09),(s*.43,-.31,1.15),m,.065) + if ghost: + for k in range(7): + a=2*pi*k/7 + hd_curve('Body_Shroud'+str(k),[(.18*cos(a),.14*sin(a),1.0),(.25*cos(a+.3),.21*sin(a+.3),.59),(.14*cos(a+.6),.16*sin(a+.6),.18),(.30*cos(a+.8),.21*sin(a+.8),.04)],[.08,.09,.048,0],m['basalt'] if k%2 else m['dark'],12,6) + hd_ring('Body_RiftHalo',(0,.08,1.71),.31,.019,m['rift'],(pi/2,0,0),48) + else: + hd_legs(m,.18,.85,True) + for s in [-1,1]: + hd_curve('Weapon_Bow'+str(s),[(0,-.44,1.11),(s*.37,-.44,1.11),(s*.64,-.25,1.15)],[.05,.044,.022],m['bone'],12,6) + hd_curve('Weapon_String'+str(s),[(s*.64,-.25,1.15),(0,-.16,1.15)],[.009,.009],m['rift'],8,2) + hd_rod('Weapon_Arrow',(0,-.15,1.15),(0,-.92,1.15),.02,m['rift'],12) + + +def hd_mask(name,loc,r,m): + x,y,z=loc + outline=[(-r*.78,r*.58),(-r*.44,r),(.44*r,r),(.78*r,.58*r),(.61*r,-.62*r),(0,-r),(-.61*r,-.62*r)] + hd_plate(name+'_Porcelain',loc,outline,r*.32,m['bone'],.015,.025) + for s in [-1,1]: + hd_plate(name+'_EyeSocket'+str(s),(x+s*r*.33,y-r*.195,z+r*.15),[(-r*.21,r*.08),(r*.21,r*.08),(r*.16,-r*.12),(-r*.12,-r*.16)],.025,m['dark'],.003) + hd_curve(name+'_EyeLight'+str(s),[(x+s*r*.33-r*.13,y-r*.23,z+r*.12),(x+s*r*.33+r*.12,y-r*.23,z+r*.12)],[r*.027]*2,m['rift'],8,2) + hd_plate(name+'_Nose',(x,y-r*.22,z-r*.10),[(-r*.12,r*.25),(r*.12,r*.25),(0,-r*.1)],.055,m['edge'],.004) + for k in range(3): + hd_box(name+'_MouthSlit'+str(k),(x+(k-1)*r*.16,y-r*.18,z-r*.54),(r*.055,.017,r*.18),m['dark'],.003) + + +def build_expedition_enemy(id,m): + """Four distinct expedition silhouettes; every part uses the same rigid rig contract.""" + stone=dict(m); stone['gold']=m['bone'];stone['gold_light']=m['edge'] + if id=='e05': + # Broad hunchback; massive capped stone gauntlets distinguish this bruiser. + hd_legs(stone,.32,.60) + hd_rock('Body_BruteCore',(0,.06,1.03),(.43,.31,.48),m['dark'],2) + for j in range(3): + z=.75+j*.22 + for s in [-1,1]: + hd_plate('Body_Chest%d_%d'%(j,s),(s*.21,-.245,z),[(-.20,-.09),(.18,-.10),(.22,.11),(-.14,.14)],.15,m['basalt'],.024,.035) + hd_curve('Body_RiftCrack',[(0,-.34,.66),(.025,-.36,.91),(-.03,-.36,1.14),(0,-.34,1.30)],[.018]*4,m['rift'],8,3) + for j in range(4): + hd_rock('Body_BackSlab'+str(j),(0,.23,.76+j*.21),(.45,.23,.17),m['basalt'],j) + hd_mask('Head_Mask',(0,-.25,1.49),.20,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.43,.045,1.32),(s*.65,-.02,1.00),(s*.65,-.15,.54),stone,.175) + hd_box('Arm'+side+'_StoneHammer',(s*.65,-.17,.52),(.42,.48,.36),m['basalt'],.06) + for k in range(3): + hd_box('Arm'+side+'_Knuckle'+str(k),(s*.65+(k-1)*.12,-.419,.57),(.10,.07,.18),m['bone'],.022) + hd_box('Arm'+side+'_Cuff',(s*.65,-.11,.72),(.44,.38,.075),m['edge'],.018) + for k in range(3): + hd_curve('Body_ShoulderSpike'+side+str(k),[(s*(.29+k*.13),.05,1.41),(s*(.36+k*.16),.065,1.70-k*.07)],[.10,0],m['bone'],12,5) + elif id in ('e06','e09'): + boss=id=='e09' + # Floating knotted robe and staff. The judge has a wide suspended mask crown. + hd_rock('Body_RobeCore',(0,.015,1.02),(.23,.19,.41),m['dark'],3) + for k in range(9): + a=k*2*pi/9 + hd_curve('Body_RobeFold'+str(k),[(.19*cos(a),.14*sin(a),1.31),(.25*cos(a+.15),.22*sin(a+.15),.84),(.30*cos(a+.25),.27*sin(a+.25),.32),(.37*cos(a+.2),.30*sin(a+.2),.10)], [.065,.082,.054,.009],m['basalt'] if k%2 else m['dark'],12,7) + for j in range(4): + hd_ring('Body_KnotRing'+str(j),(0,0,.92+j*.085),.245-j*.012,.019,m['bone'],segments=40) + hd_mask('Head_Face',(0,-.015,1.60),.235 if boss else .195,m) + for s,side in [(-1,'L'),(1,'R')]: + hd_arm('Arm'+side,(s*.26,0,1.29),(s*.38,-.11,1.04),(s*.43,-.26,1.22),stone,.081) + hd_plate('Arm'+side+'_Pauldron',(s*.28,0,1.34),[(-.12,.02),(0,.16),(.16,.06),(.12,-.13),(-.10,-.13)],.19,m['bone'],.018) + hd_curve('Weapon_Staff',[(.47,-.28,.12),(.46,-.28,.73),(.45,-.27,1.35),(.49,-.27,1.83)],[.028,.035,.035,.025],m['bone'],12,8) + for k in range(5): + hd_ring('Weapon_StaffCollar'+str(k),(.475,-.275,.68+k*.12),.045,.012,m['edge'],segments=24) + hd_ring('Weapon_StaffKnot',(.49,-.27,1.82),.17,.03,m['bone'],(pi/2,0,0),48) + hd_rock('Weapon_StaffHeart',(.49,-.27,1.82),(.105,.06,.105),m['rift'],0) + for s in [-1,1]: + hd_curve('Weapon_KnotBranch'+str(s),[(.48+s*.06,-.27,1.68),(.48+s*.20,-.27,1.84),(.48+s*.11,-.26,1.99)],[.028,.022,0],m['bone'],10,7) + if boss: + hd_ring('Body_JudgeHalo',(0,.12,1.53),.65,.034,m['bone'],(pi/2,0,0),72) + hd_ring('Body_JudgeGlow',(0,.135,1.53),.60,.012,m['rift'],(pi/2,0,0),72) + for k in range(5): + a=.12*pi+k*.19*pi + x=.65*cos(a);z=1.53+.65*sin(a) + hd_mask('Body_CourtMask'+str(k),(x,.065,z),.16,m) + hd_curve('Body_CrownSpike'+str(k),[(x,.14,z+.12),(x*1.07,.14,z+.32)],[.065,0],m['bone'],10,5) + for s in [-1,1]: + hd_curve('Body_Chains'+str(s),[(s*.54,.10,1.63),(s*.64,-.03,1.07),(s*.46,-.16,.47)],[.018]*3,m['bone'],10,9) + else: + for j in range(3): + hd_ring('Body_HealingKnot'+str(j),((j-1)*.13,-.205,1.09),.084,.019,m['rift'],(pi/2,0,.4*j),40) + else: + # Final boss: four heavy legs, segmented carapace, actual open maw and a crown. + hd_rock('Body_CrownCore',(0,.13,.98),(.54,.58,.52),m['dark'],1) + for s,side in [(-1,'L'),(1,'R')]: + for j,y in enumerate([-.10,.64]): + n='Leg'+side+str(j);hip=(s*.40,y,.92);knee=(s*.66,y+.06,.51);foot=(s*.70,y-.10,.12) + hd_rod(n+'_Inner',hip,knee,.10,m['dark']) + hd_rock(n+'_Thigh',tuple((Vector(hip)+Vector(knee))*.5),(.18,.19,.30),m['basalt'],j) + hd_rock(n+'_Shin',tuple((Vector(knee)+Vector(foot))*.5),(.16,.18,.24),m['basalt'],j+1) + hd_disc(n+'_Joint',(knee[0],knee[1]-.18,knee[2]),.105,.045,m['bone']) + for k in range(3): + x=foot[0]+(k-1)*.09 + hd_curve(n+'_Claw'+str(k),[(x,y-.05,.19),(x,y-.27,.10),(x,y-.39,.055)],[.064,.043,0],m['bone'],12,5) + for j in range(4): + hd_rock('Body_Shell'+side+str(j),(s*.37,.02+j*.20,1.20),(.25,.19,.28),m['basalt'],j) + hd_curve('Body_Ridge'+side+str(j),[(s*.32,.02+j*.20,1.37),(s*.41,.06+j*.20,1.67),(s*.30,.14+j*.20,1.78)],[.105,.069,0],m['bone'],12,6) + hd_disc('Head_MawVoid',(0,-.43,.99),.40,.15,m['dark']) + hd_ring('Head_MawRim',(0,-.53,.99),.38,.065,m['basalt'],(pi/2,0,0),64) + hd_disc('Head_RiftThroat',(0,-.522,.99),.22,.025,m['rift']) + for k in range(14): + a=k*2*pi/14 + hd_curve('Head_Tooth'+str(k),[(.35*cos(a),-.58,.99+.35*sin(a)),(.29*cos(a),-.63,.99+.29*sin(a)),(.19*cos(a+.1),-.60,.99+.19*sin(a+.1))],[.058,.044,0],m['bone'],12,5) + for s in [-1,1]: + hd_rock('Head_Brow'+str(s),(s*.24,-.34,1.41),(.27,.17,.16),m['basalt'],s) + hd_curve('Head_Eye'+str(s),[(s*.12,-.498,1.41),(s*.31,-.49,1.45)],[.023,.029],m['rift'],10,4) + hd_ring('Head_CrownBand',(0,.02,1.63),.36,.052,m['bone'],segments=64) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_CrownPoint'+str(k),[(.36*cos(a),.02+.36*sin(a),1.62),(.47*cos(a),.02+.47*sin(a),1.91),(.37*cos(a),.02+.37*sin(a),2.20 if k%2 else 2.06)],[.095,.065,0],m['bone'],12,7) + hd_rock('Head_CrownGem'+str(k),(.38*cos(a),.02+.38*sin(a),1.69),(.055,)*3,m['rift'],k) + hd_curve('Body_Tail',[(0,.61,.86),(0,.97,.66),(.18,1.13,.35),(.30,1.22,.25)],[.14,.11,.06,0],m['basalt'],16,8) + + +def enhance_existing(spec,m): + """Round existing neutral/environment geometry and add constructed details.""" + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH':continue + dimensions=obj.dimensions + width=min(min(dimensions)*.09,.014) + hd_finish(obj,max(.001,width),3) + if spec['role']=='lane': + hd_materials(m) + # Detailed edge stones, anchored brass plates and inset light wells. + for s in [-1,1]: + for j in range(4): + y=-1.5+j + hd_box('Body_EdgeStone%d_%d'%(s,j),(s*6.13,y,.16),(.30,.91,.29),m['basalt'],.035) + hd_box('Body_EdgeCap%d_%d'%(s,j),(s*6.13,y,.32),(.34,.92,.060),m['gold'],.014) + for j,y in enumerate([-.95,.95]): + hd_box('Body_LightRecess%d_%d'%(s,j),(s*6.13,y,.364),(.15,.22,.035),m['dark'],.009) + hd_box('Body_LightGlass%d_%d'%(s,j),(s*6.13,y,.387),(.065,.14,.013),m['ember'],.005) + elif spec['role']=='core': + hd_materials(m) + for k in range(8): + a=k*pi/4 + hd_box('Body_PlinthArmor'+str(k),(1.02*cos(a),1.02*sin(a),.18),(.37,.25,.29),m['basalt'],.029,rotation=(0,0,a+pi/2)) + hd_ring('Body_PlinthGold'+str(k),(1.04*cos(a),1.04*sin(a),.35),.068,.012,m['gold'],segments=24) + hd_ring('Body_OuterRim',(0,0,.36),1.19,.026,m['gold'],segments=72) + + +def finalize_high_geometry(): + """Resolve tiny bevel slivers and retain valid corner normals after triangulation. + + Thin inset discs can produce normals across their back edge when weighted + normals are computed on n-gons. Triangulate first, then constrain only those + corner normals that point below the actual triangle surface. + """ + for obj in bpy.context.scene.objects: + if obj.type != 'MESH': continue + mesh=obj.data + bm=bmesh.new(); bm.from_mesh(mesh) + bmesh.ops.remove_doubles(bm,verts=list(bm.verts),dist=.000001) + bmesh.ops.dissolve_degenerate(bm,edges=list(bm.edges),dist=.000001) + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bmesh.ops.triangulate(bm,faces=list(bm.faces),quad_method='BEAUTY',ngon_method='EAR_CLIP') + bm.to_mesh(mesh);bm.free();mesh.update() + normals=[tuple(n.vector) for n in mesh.corner_normals] + for face in mesh.polygons: + for index in face.loop_indices: + if Vector(normals[index]).dot(face.normal)<.01: + normals[index]=tuple(face.normal) + mesh.normals_split_custom_set(normals) + +from math import sin, cos, pi +import bpy +from mathutils import Vector + + +def living_materials(m): + colors={'bark':('503D2D',.85,0),'wood':('836343',.79,0), + 'endgrain':('92764E',.86,0),'groove':('312B24',.93,0),'moss':('3E6041',.90,0), + 'leaf':('7D9850',.65,0),'vein':('A9B875',.67,0), + 'petal':('AD6D8A',.56,0),'heart':('E9BD79',.52,0), + 'water':('65D6B5',.18,.65)} + for key,(hexcolor,rough,emission) in colors.items(): + name='SW_HD_W_'+key + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + c=tuple(srgb_to_linear(int(hexcolor[i:i+2],16)/255) for i in (0,2,4)) + mat.diffuse_color=(*c,1) + node=mat.node_tree.nodes.get('Principled BSDF') + node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Roughness'].default_value=rough + if emission: + node.inputs['Emission Color'].default_value=(*c,1) + node.inputs['Emission Strength'].default_value=emission + m[key]=mat + return m + + +def living_blob(name,loc,scale,mat): + obj=ellipsoid(name,loc,scale,mat,subdivisions=2 if max(scale) < .085 else 3) + if 'bark' in mat.name or 'moss' in mat.name: + for v in obj.data.vertices: + p=v.co + p *= 1+.045*sin(p.x*27+p.z*13)*cos(p.y*21) + for face in obj.data.polygons:face.use_smooth=True + return obj + + +def living_leaf(name,start,end,width,m,key='leaf'): + """Closed lenticular leaf, curved midrib and six modeled secondary veins.""" + a,b=Vector(start),Vector(end);d=b-a + tangent=d.normalized();side=tangent.cross(Vector((0,-1,.3))).normalized() + if side.length<.1:side=Vector((1,0,0)) + normal=side.cross(tangent).normalized() + verts=[]; rows=9; sides=8 + for j in range(rows): + t=.005+.99*j/(rows-1) + center=a+d*t+normal*(sin(t*pi)*width*.20) + w=max(.001,sin(t*pi)**.85*width*(1+.045*sin(t*13*pi))) + for k in range(sides): + angle=2*pi*k/sides + verts.append(tuple(center+side*cos(angle)*w+normal*sin(angle)*w*.18)) + faces=[tuple(reversed(range(sides)))] + for j in range(rows-1): + for k in range(sides): + n=(k+1)%sides;faces.append((j*sides+k,j*sides+n,(j+1)*sides+n,(j+1)*sides+k)) + faces.append(tuple((rows-1)*sides+k for k in range(sides))) + obj=mesh_object(name,verts,faces,m[key]) + for face in obj.data.polygons:face.use_smooth=True + points=[a+d*t+normal*(sin(t*pi)*width*.39+.005) for t in [0,.3,.65,1]] + hd_curve(name+'_Midrib',points,[.009,.009,.006,.001],m['vein'],6,3) + for j in range(3): + t=.25+j*.20 + center=a+d*t+normal*(sin(t*pi)*width*.39+.008) + for sign in [-1,1]: + tip=a+d*(t+.12)+side*sign*width*sin((t+.12)*pi)*.8+normal*width*.24 + hd_curve(name+'_Vein%d_%d'%(j,sign),[center,(center+tip)*.5+normal*.005,tip],[.004,.003,.001],m['vein'],5,2) + return obj + + +def living_branch(name,points,radius,m,grooves=3): + points=[Vector(p) for p in points] + obj=hd_curve(name,points,[radius*(1-.60*j/(len(points)-1)) for j in range(len(points))],m['bark'],16,7) + for vertex in obj.data.vertices: + p=vertex.co + vertex.co += Vector((sin(p.z*35+p.y*17),cos(p.z*27+p.x*18),sin(p.x*19+p.y*31)))*radius*.11 + for k in range(grooves): + angle=2*pi*k/max(1,grooves) + ridges=[p+Vector((cos(angle),sin(angle),0))*radius*(.96-.57*j/(len(points)-1)) for j,p in enumerate(points)] + hd_curve(name+'_Grain'+str(k),ridges,[radius*.11]*(len(points)-1)+[.001],m['wood'],6,5) + + +def living_roots(m,count=4,spread=.43,height=.55,radius=.12): + for k in range(count): + a=2*pi*k/count+pi/4 + group=('LegL' if cos(a)<0 else 'LegR')+('1' if k>=2 else '') + hip=Vector((.13*cos(a),.13*sin(a),height)) + knee=Vector((spread*.70*cos(a),spread*.60*sin(a),.31)) + foot=Vector((spread*cos(a),spread*sin(a),.12)) + living_branch(group+'_Root',[hip,knee,foot],radius,m,5) + for j in range(3): + angle=a+(j-1)*.48 + tip=foot+Vector((.24*cos(angle),.24*sin(angle),-.10)) + hd_curve(group+'_Toe'+str(j),[knee*.18+foot*.82,foot+Vector((.09*cos(angle),.09*sin(angle),.025)),tip],[radius*.65,radius*.4,.003],m['wood'],12,6) + hd_curve(group+'_Moss',[hip+Vector((0,-radius*.6,0)),knee+Vector((0,-radius*.7,0)),foot],[radius*.28,radius*.22,.001],m['moss'],10,5) + living_leaf(group+'_Sprout',knee,knee+Vector((.14*cos(a),-.035,.17)),.055,m) + + +def living_flower(name,loc,m,scale=1): + center=Vector(loc) + for k in range(5): + angle=k*2*pi/5 + p=center+Vector((.035*cos(angle),-.008,.035*sin(angle)))*scale + obj=living_blob(name+'_Petal'+str(k),p,(.027*scale,.012*scale,.040*scale),m['petal']) + obj.rotation_euler.y=pi/2-angle + living_blob(name+'_Pollen',center+Vector((0,-.022,0))*scale,(.017*scale,)*3,m['heart']) + + +def living_trunk(m,height=.85,radius=.14,base=.35,count=4): + for k in range(count): + phase=2*pi*k/count + points=[] + for j in range(7): + t=j/6;a=phase+t*pi*1.8 + points.append((radius*cos(a),radius*sin(a),base+t*height)) + living_branch('Body_Braid'+str(k),points,.073 if count<5 else .09,m,3) + for k in range(8): + a=k*2.4;z=base+.15+k*height*.08 + start=(radius*cos(a),radius*sin(a),z) + living_leaf('Body_TrunkLeaf'+str(k),start,(.34*cos(a),.30*sin(a),z+.16),.064,m) + + +def living_bark(name,loc,width,height,m,seed=0): + outline=[(-width*.46,height*.44),(-width*.05,height*.56),(width*.49,height*.35),(width*.46,-height*.29),(width*.12,-height*.54),(-width*.44,-height*.40)] + obj=hd_plate(name,loc,outline,.075,m['wood'],.012,.045) + x,y,z=loc + for j in range(4): + dx=(j-1.5)*width*.19 + hd_curve(name+'_Fissure'+str(j),[(x+dx,y-.074,z-height*.29),(x+dx+.008*sin(seed+j),y-.096,z),(x+dx-.01,y-.068,z+height*.33)],[.005,.008,.004],m['bark'],6,3) + return obj + + +def living_thorn(up,m): + living_roots(m,4 if up else 2,.38 if up else .32,.52,.12) + if not up: + living_blob('Body_MossHeart',(0,.02,.83),(.34,.28,.40),m['moss']) + for k in range(6): + a=k*pi/3 + points=[] + for j in range(6): + t=j/5;radius=.18+.17*sin(t*pi) + points.append((radius*cos(a+t*.8),radius*.86*sin(a+t*.8),.48+t*.68)) + living_branch('Body_WovenBark'+str(k),points,.037,m,2) + for k in range(4): + a=k*pi/2 + living_leaf('Body_ShoulderLeaf'+str(k),(.20*cos(a),.20*sin(a),1.07),(.34*cos(a),.31*sin(a),1.24),.064,m) + for k in range(9): + a=k*2*pi/9 + # Local bark plates turn as a whole, including their carved lines. + before=set(bpy.context.scene.objects) + living_bark('Body_Bark'+str(k),(0,-.275,.84),.23,.54,m,k) + for o in set(bpy.context.scene.objects)-before: + from mathutils import Matrix + mat=Matrix.Rotation(a,4,'Z');o.location=mat@o.location;o.rotation_euler.z=a + hd_curve('Body_Thorn'+str(k),[(.28*cos(a),.25*sin(a),.88),(.45*cos(a),.39*sin(a),1.01),(.56*cos(a),.48*sin(a),1.08)],[.08,.045,.001],m['leaf'],12,6) + hd_plate('Head_EyeShadow',(0,-.339,.85),[(-.20,.026),(.20,.026),(.12,-.029),(-.16,-.025)],.025,m['groove'],.004) + for sign in [-1,1]: + hd_disc('Head_Eye'+str(sign),(sign*.11,-.36,.85),.017,.014,m['heart']) + living_leaf('Head_Sprout'+str(sign),(0,0,1.18),(sign*.20,.02,1.48),.093,m) + living_flower('Body_Blossom',(-.24,-.20,1.11),m) + else: + living_trunk(m,.60,.23,.31,5) + living_blob('Head_JawDark',(0,-.12,.94),(.36,.32,.19),m['groove']) + for upper,z in [(True,1.13),(False,.72)]: + name='Head_Upper' if upper else 'Head_Lower' + living_blob(name+'_Jaw',(0,-.14,z),(.41,.38,.13),m['bark']) + for row in range(3): + hd_curve(name+'_Lip'+str(row),[(-.32,.02,z),(-.40,-.25,z+.015*row),(-.20,-.51,z+.02*row),(0,-.54,z),( .20,-.51,z+.02*row),(.40,-.25,z+.015*row),(.32,.02,z)],[.05]*7,m['moss'] if row==0 else m['wood'],12,5) + for k in range(9): + a=pi+(k/8)*pi + x=.35*cos(a);y=-.17+.34*sin(a) + hd_curve(name+'_Fang'+str(k),[(x,y,z+(-.05 if upper else .06)),(x*.97,y-.015,z+(-.11 if upper else .10)),(x*.9,y-.03,z+(-.24 if upper else .20))],[.045,.028,.001],m['heart'],12,5) + for k in range(6): + a=k*pi/3 + living_leaf('Head_JawLeaf'+str(k),(.26*cos(a),.21*sin(a),1.13),(.49*cos(a),.41*sin(a),1.30),.11,m) + living_flower('Head_JawFlower',(-.32,-.20,1.26),m) + + +def living_log(name,loc,r,m): + hd_disc(name+'_Bark',loc,r,.15,m['bark']) + x,y,z=loc + cut=hd_disc(name+'_Cut',(x,y-.086,z),r*.86,.025,m['endgrain']) + # Local UVs retain the centre of each log when parts are batched for Godot. + uv=cut.data.uv_layers.active or cut.data.uv_layers.new(name='GrowthRings') + for loop in cut.data.loops: + v=cut.data.vertices[loop.vertex_index].co + uv.data[loop.index].uv=(.5+v.x/(r*1.72),.5+v.y/(r*1.72)) + for j in range(6): + radius=r*(.11+j*.127) + verts=[];faces=[];segments=64;sides=6 + for k in range(segments): + a=k*2*pi/segments + organic=1+.045*sin(a*3+j*.61)+.035*cos(a*7-j) + for side in range(sides): + b=side*2*pi/sides + rr=radius*organic+.0019*cos(b) + verts.append((x+rr*cos(a),y-.102+.0019*sin(b),z+rr*sin(a))) + for k in range(segments): + for side in range(sides): + a=k*sides+side;b=k*sides+(side+1)%sides + c=((k+1)%segments)*sides+(side+1)%sides;d=((k+1)%segments)*sides+side + faces.append((a,b,c,d)) + mesh_object(name+'_Growth'+str(j),verts,faces,m['bark']) + for k in range(13): + a=k*2*pi/13 + hd_curve(name+'_RoughEdge'+str(k),[(x+r*.92*cos(a),y+.045,z+r*.92*sin(a)),(x+r*cos(a),y-.025,z+r*sin(a)),(x+r*.94*cos(a),y-.09,z+r*.94*sin(a))],[.017,.027,.015],m['wood'],8,4) + for k in range(3): + a=k*2.7+r + hd_curve(name+'_Split'+str(k),[(x+r*.84*cos(a),y-.105,z+r*.84*sin(a)),(x+r*.66*cos(a+.015),y-.109,z+r*.66*sin(a+.015)),(x+r*.50*cos(a-.023),y-.109,z+r*.50*sin(a-.023))],[.0038,.0023,.0007],m['groove'],5,2) + + +def living_tank(up,m): + living_roots(m,4,.44,.57,.14) + living_trunk(m,.70,.20,.32,5) + living_blob('Body_InnerMoss',(0,.08,.86),(.41,.31,.40),m['moss']) + if up: + from mathutils import Matrix + for row in range(3): + for k in range(8): + a=k*2*pi/8+row*.24 + before=set(bpy.context.scene.objects) + living_bark('Body_OverlappingBark%d_%d'%(row,k),(0,-.30,.62+row*.23),.22,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.location.y+=.08;obj.rotation_euler.z=a + for k,(x,y,z,r) in enumerate([(-.28,-.22,1.04,.31),(.28,-.19,.87,.27),(0,.02,1.34,.20),(-.36,-.18,.55,.15),(.39,-.15,.57,.15),(0,.37,1.02,.26)]): + living_log('Body_Log'+str(k),(x,y,z),r,m) + else: + for row in range(3): + for k in range(7): + a=k*2*pi/7+row*.45 + from mathutils import Matrix + before=set(bpy.context.scene.objects) + living_bark('Body_Cork%d_%d'%(row,k),(0,-(.40-row*.07),.64+row*.23),.26,.31,m,k+row) + rotation=Matrix.Rotation(a,4,'Z') + for obj in set(bpy.context.scene.objects)-before: + obj.location=rotation@obj.location;obj.rotation_euler.z=a + for k in range(11): + a=k*2.4 + z=1.22+(k%3)*.07 + living_leaf('Head_Canopy'+str(k),(.12*cos(a),.10*sin(a),z),(.37*cos(a),.30*sin(a),z+.15),.073,m) + for k in range(5): + living_flower('Body_Flower'+str(k),(-.30+k*.15,-.26,1.10+.12*sin(k*2)),m,.7) + + +def living_cup(name,loc,r,m,flower=False): + x,y,z=loc + material=m['petal'] if flower else m['moss'] + obj=r_lathe(name+'_Shell',loc,[(0,0),(r*.2,.02),(r*.42,.07),(r*.8,.19),(r,.32),(r*1.02,.35),(r*.94,.365),(r*.76,.24),(r*.4,.12),(0,.09)],material,segments=48) + for p in obj.data.polygons:p.use_smooth=True + hd_ring(name+'_Rim',(x,y,z+.35),r,.024,m['leaf'],segments=64) + count=(12 if r > .2 else 5) if flower else 10 + for k in range(count): + a=k*2*pi/count + hd_curve(name+'_Rib'+str(k),[(x+r*.2*cos(a),y+r*.2*sin(a),z+.06),(x+r*.54*cos(a),y+r*.54*sin(a),z+.12),(x+r*.90*cos(a),y+r*.9*sin(a),z+.30)],[.015,.017,.008],m['wood'] if not flower else m['petal'],8,5) + if flower: + living_leaf(name+'_Fringe'+str(k),(x+r*.98*cos(a),y+r*.98*sin(a),z+.34),(x+r*1.08*cos(a),y+r*1.08*sin(a),z+.17),.047,m) + + +def living_ranged(up,m): + living_roots(m,4 if up else 2,.32,.48,.09) + living_trunk(m,.77,.09,.32,4) + living_cup('Head_Launcher',(0,-.04,1.03),.30 if up else .26,m) + living_blob('Head_Seed',(0,-.04,1.31),(.15,.145,.20 if up else .12),m['wood']) + for k in range(7): + a=k*2*pi/7 + hd_curve('Head_SeedSeam'+str(k),[(.10*cos(a),-.04+.10*sin(a),1.24),(.151*cos(a),-.04+.145*sin(a),1.34),(0,-.04,1.51 if up else 1.43)],[.006,.007,.001],m['bark'],6,4) + for k in range(12 if up else 5): + a=k*2*pi/(6 if up else 5) + row=k//6 if up else 0 + living_leaf('Head_LauncherScale'+str(k),(.13*cos(a),-.04+.13*sin(a),1.06+.12*row),(.36*cos(a),-.04+.36*sin(a),1.51+.08*row),.13 if up else .10,m,'wood' if up else 'leaf') + for sign in [-1,1]: + living_leaf('Body_BroadLeaf'+str(sign),(sign*.04,0,.64),(sign*.43,-.02,.94),.13,m) + living_flower('Body_Flower'+str(sign),(sign*.11,-.11,.81),m,.65) + + +def living_artillery(up,m): + living_roots(m,4,.43,.56,.12) + living_trunk(m,.92 if up else .65,.14,.32,4) + positions=[(-.30,-.03,.78,.30),(.30,.03,.68,.29),(0,.10,1.29,.43)] if up else [(0,0,.96,.48)] + for k,(x,y,z,r) in enumerate(positions): + living_branch('Body_FungalTrunk'+str(k),[(0,0,.4),(x*.6,y,.74),(x,y,z+.02)],.11,m,4) + living_cup('Head_Cup'+str(k),(x,y,z),r,m,True) + for j in range(5): + a=j*2*pi/5 + living_blob('Weapon_Spore%d_%d'%(k,j),(x+r*.30*cos(a),y+r*.30*sin(a),z+.18),(.045,.043,.083),m['heart']) + for k in range(4 if up else 2): + sign=-1 if k%2 else 1 + living_cup('Body_SmallCup'+str(k),(sign*.26,.04,.48+.13*k),.11,m,True) + + +def living_support(up,m): + living_roots(m,4 if up else 2,.39,.52,.105) + if up: + for sign in [-1,1]: + for j in range(3): + living_branch('Body_Arch%d_%d'%(sign,j),[(sign*.18,.07,.36),(sign*(.36+j*.015),.10,.83),(sign*.26,.07,1.27),(sign*.07,.08,1.48) ],.088-j*.012,m,3) + for k in range(24): + a=k*2.4;row=k//8 + living_leaf('Head_Canopy'+str(k),(.05*cos(a),.06,1.48-row*.07),(.45*cos(a),.06+.34*sin(a),1.28-row*.10),.13,m) + else: + living_trunk(m,.93,.09,.31,4) + for k in range(5): + a=k*2*pi/5 + living_leaf('Head_Crown'+str(k),(.02*cos(a),0,1.18),(.36*cos(a),.17*sin(a),1.45+(k==2)*.17),.14,m) + r=.33 if up else .25; z=.79 + living_cup('Weapon_Basin',(0,-.22,z-.16),r,m) + water=hd_finish(cylinder('Weapon_Water',(0,-.22,z+.075),r*.81,.025,m['water'],64),0,0,True) + for k in range(3): + hd_ring('Weapon_Ripple'+str(k),(0,-.22,z+.091),r*(.18+k*.24),.006,m['vein'],segments=48) + if not up:living_blob('Weapon_DewOrb',(0,-.22,z+.18),(.095,.095,.095),m['water']) + for sign,side in [(-1,'L'),(1,'R')]: + living_branch('Arm'+side+'_BasinVine',[(sign*.12,0,z+.25),(sign*.28,-.11,z+.22),(sign*r,-.22,z+.025)],.048,m,3) + for k in range(6 if up else 3): + a=k*2.4 + living_flower('Body_Blossom'+str(k),(.31*cos(a),-.15,1.25+.20*sin(a)),m,.85) + + +def build_high_wurzelbund(spec,m): + living_materials(m) + {'melee':living_thorn,'tank':living_tank,'ranged':living_ranged,'artillery':living_artillery,'support':living_support}[spec['role']](spec['upgraded'],m) + + +def build_high_worker(spec,m): + """Clay and brass gatherer: real joints, apron, gloves, tool and reservoir.""" + hd_materials(m) + for sign,side in [(-1,'L'),(1,'R')]: + name='Leg'+side + hd_rod(name+'_Shin',(sign*.15,.02,.16),(sign*.15,.02,.37),.065,m['dark']) + hd_box(name+'_Boot',(sign*.15,-.05,.095),(.22,.32,.16),m['basalt'],.045) + hd_box(name+'_Sole',(sign*.15,-.055,.035),(.235,.33,.045),m['dark'],.012) + hd_ring(name+'_Cuff',(sign*.15,.02,.22),.082,.019,m['gold'],segments=40) + for j in range(3): + hd_box(name+'_ToeRidge'+str(j),(sign*.15,-.13+j*.055,.179),(.18,.018,.012),m['gold'],.003) + living_blob('Body_ClayTorso',(0,.025,.53),(.23,.17,.25),m['ceramic']) + hd_plate('Body_LeatherApron',(0,-.154,.48),[(-.17,.17),(.17,.17),(.21,-.20),(-.21,-.20)],.045,m['basalt'],.018,.02) + for j in range(7): + hd_disc('Body_ApronRivet'+str(j),(-.16+j*.053,-.19,.40),.009,.012,m['gold_light']) + hd_box('Body_ToolPocket',(0,-.195,.50),(.20,.025,.10),m['gold'],.012) + for sign in [-1,1]: + hd_curve('Body_Harness'+str(sign),[(sign*.17,-.18,.58),(sign*.15,-.13,.73),(sign*.12,.05,.78),(sign*.17,.17,.59)],[.019]*4,m['gold'],10,5) + living_blob('Head_Hood',(0,.015,.85),(.22,.19,.21),m['basalt']) + hd_disc('Head_FaceRecess',(0,-.18,.85),.145,.03,m['dark']) + for sign in [-1,1]: + hd_disc('Head_GoggleSocket'+str(sign),(sign*.075,-.205,.87),.064,.036,m['gold']) + hd_disc('Head_GoggleLens'+str(sign),(sign*.075,-.229,.87),.048,.019,m['bone']) + hd_disc('Head_GoggleGlint'+str(sign),(sign*.069,-.241,.885),.016,.009,m['ceramic']) + hd_plate('Head_Cap',(0,-.01,1.005),[(-.24,0),(-.14,.055),(.14,.055),(.24,0),(.14,-.016),(-.14,-.016)],.37,m['gold'],.012) + hd_disc('Head_LampHousing',(0,-.19,1.017),.038,.035,m['dark']) + hd_disc('Head_Lamp',(0,-.213,1.017),.025,.013,m['hot']) + hd_finish(cylinder('Body_Reservoir',(0,.235,.62),.16,.35,m['bone'],32),.01,3,True) + for z in [.45,.79]: + hd_ring('Body_TankRim'+str(z),(0,.235,z),.17,.025,m['gold'],segments=48) + for k in range(8): + a=k*pi/4 + hd_rod('Body_TankBrace'+str(k),(.17*cos(a),.235+.17*sin(a),.45),(.17*cos(a),.235+.17*sin(a),.79),.012,m['gold']) + for sign,side in [(-1,'L'),(1,'R')]: + a=(sign*.21,.0,.66);b=(sign*.30,-.08,.50);c=(sign*.29,-.19,.55) + hd_rod('Arm'+side+'_Upper',a,b,.065,m['basalt']) + hd_rod('Arm'+side+'_Forearm',b,c,.06,m['ceramic']) + hd_disc('Arm'+side+'_Elbow',(b[0],b[1]-.04,b[2]),.053,.04,m['gold']) + living_blob('Arm'+side+'_Glove',c,(.066,.06,.072),m['dark']) + for j in range(3): + hd_rod('Arm'+side+'_Finger'+str(j),(c[0]+(j-1)*.025,c[1]-.045,c[2]),(c[0]+(j-1)*.025,c[1]-.049,c[2]-.055),.013,m['gold']) + hd_rod('WeaponL_Handle',(-.30,-.22,.23),(-.30,-.22,.93),.025,m['gold']) + hd_curve('WeaponL_Fork',[(-.44,-.22,.87),(-.40,-.22,.76),(-.30,-.22,.74),(-.20,-.22,.76),(-.16,-.22,.87)],[.022]*5,m['bone'],12,5) + hd_rod('WeaponR_Probe',(.29,-.22,.53),(.40,-.34,.72),.027,m['gold']) + + +def build_high_core(spec,m): + """Cut mineral held by an engraved stone/brass cradle and satellite shards.""" + hd_materials(m) + team=int(spec.get('team',0)) + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + color=('65D9C1' if team==0 else 'EE9B82') + c=tuple(srgb_to_linear(int(color[i:i+2],16)/255) for i in (0,2,4)) + node=crystal.node_tree.nodes.get('Principled BSDF');node.inputs['Base Color'].default_value=(*c,1) + node.inputs['Metallic'].default_value=.28;node.inputs['Roughness'].default_value=.20 + node.inputs['Emission Color'].default_value=(*c,1);node.inputs['Emission Strength'].default_value=.65 + crystal.diffuse_color=(*c,1) + for j,(r,z,h) in enumerate([(1.20,.12,.24),(1.07,.27,.10),(.88,.39,.18),(.68,.51,.12)]): + hd_finish(cylinder('Body_CoreStep'+str(j),(0,0,z),r,h,m['basalt'],48),.027,3) + hd_ring('Body_CoreStepRim'+str(j),(0,0,z+h*.44),r*.98,.018,m['gold'],segments=64) + if team == 1: + corners=[Vector((.97*cos(k*2*pi/3),.97*sin(k*2*pi/3),.367)) for k in range(3)] + for k in range(3): + hd_rod('Team_Triangle'+str(k),corners[k],corners[(k+1)%3],.022,crystal) + else: + hd_ring('Team_Circle',(0,0,.367),.97,.022,crystal,segments=64) + for k in range(12): + a=k*pi/6 + hd_box('Body_PlinthBlock'+str(k),(1.08*cos(a),1.08*sin(a),.21),(.23,.25,.24),m['edge'],.025,rotation=(0,0,a)) + hd_ring('Body_Seal'+str(k),(1.06*cos(a),1.06*sin(a),.346),.042,.009,m['gold_light'],segments=24) + hd_rod('Body_RadialInlay'+str(k),(.90*cos(a),.90*sin(a),.453),(.60*cos(a),.60*sin(a),.453),.012,crystal) + for k in range(6): + a=k*pi/3 + hd_curve('Body_Cradle'+str(k),[(.66*cos(a),.66*sin(a),.47),(.75*cos(a),.75*sin(a),.67),(.60*cos(a),.60*sin(a),1.02),(.43*cos(a),.43*sin(a),1.14)],[.09,.083,.060,.035],m['gold'],16,7) + hd_ring('Body_CradleCollar'+str(k),(.60*cos(a),.60*sin(a),.90),.065,.015,m['gold_light'],segments=32) + def shard(name,loc,r,height,tilt=0): + vertices=[(0,0,-height*.45)] + for j,(radius,z) in enumerate([(r*.78,-height*.23),(r,height*.13),(r*.72,height*.31)]): + for k in range(7): + a=k*2*pi/7+.10*j + vertices.append((radius*cos(a),radius*sin(a),z)) + vertices.append((r*.16,0,height*.57));faces=[] + for k in range(7):faces.append((0,1+(k+1)%7,1+k)) + for j in range(2): + for k in range(7): + a=1+j*7+k;b=1+j*7+(k+1)%7;faces.append((a,b,b+7,a+7)) + for k in range(7):faces.append((15+k,15+(k+1)%7,22)) + obj=mesh_object(name,vertices,faces,crystal);obj.location=loc;obj.rotation_euler=(tilt,tilt*.4,0) + hd_finish(obj,.006,2) + shard('Core_CrystalMain',(0,0,1.41),.41,1.68) + for k in range(5): + a=k*2*pi/5 + shard('Core_CrystalSatellite'+str(k),(.43*cos(a),.43*sin(a),.89+(k%2)*.10),.15,.71,.18*cos(a)) + hd_ring('Body_CrystalHalo',(0,0,1.19),.60,.021,m['gold_light'],segments=72) + +import bpy, bmesh +from math import sin, cos +from mathutils import Vector, noise + + +def sculpt_game_surfaces(spec): + if spec['faction'] not in ['glutpakt','wurzelbund','rift'] and spec['role'] not in ['worker','core']: + return + candidates=[] + for obj in list(bpy.context.scene.objects): + if obj.type!='MESH' or not obj.data.materials: continue + mat=obj.data.materials[0].name + kind='bark' if mat.startswith('SW_HD_W_') and any(k in mat for k in ['bark','wood']) else 'rock' if any(k in mat for k in ['SW_HD_basalt','SW_HD_edge']) else '' + # Tiny strands and thin trim already carry explicit modeled details. + if not kind or len(obj.data.polygons)<20 or any(k in obj.name for k in ['Grain','Vein','Ring','Trim','Rim','Groove','Toe','Fang']): continue + bpy.context.view_layer.update() + if spec["faction"]=="wurzelbund" and any(k in obj.name for k in ["Scale","Rib","Growth","Split"]): continue + extent=max(obj.dimensions) + if extent < .16: continue + candidates.append((extent,obj,kind)) + candidates.sort(key=lambda row:row[0],reverse=True) + for extent,obj,kind in candidates[:18]: + bpy.context.view_layer.objects.active=obj + # Bake existing scale, keeping the semantic part transform intact. + from mathutils import Matrix + obj.data.transform(Matrix.Diagonal((*obj.scale,1))) + obj.scale=(1,1,1) + bm=bmesh.new();bm.from_mesh(obj.data) + bmesh.ops.subdivide_edges(bm,edges=list(bm.edges),cuts=1,use_grid_fill=True) + bm.normal_update() + amplitude=min(.014,extent*.023) if kind=='bark' else min(.009,extent*.012) + for v in bm.verts: + p=v.co + n=noise.noise_vector(p*19+Vector((1.7,3.2,.6))) + if kind=='bark': + grain=noise.noise(Vector((p.x*46,p.y*46,p.z*5.5))) + ridges=sin(p.x*103+p.y*81+n.z*1.3) + amount=(grain*.7+ridges*.3)*amplitude + else: + amount=(n.x*.8+noise.noise(p*61)*.2)*amplitude + v.co+=v.normal*amount + bmesh.ops.recalc_face_normals(bm,faces=list(bm.faces)) + bm.to_mesh(obj.data);bm.free();obj.data.update() + for face in obj.data.polygons: face.use_smooth=True + obj['sculpt_surface']=kind + obj['relief_depth_m']=amplitude + + +def add_offline_sculpt_modifiers(objects): + """Only called AFTER GLB export. Render-visible high mesh remains editable.""" + for obj in objects: + if obj.type!='MESH' or not obj.get('sculpt_surface'): continue + subdiv=obj.modifiers.new('HIGH RES · surface refinement','SUBSURF') + subdiv.subdivision_type='SIMPLE';subdiv.levels=1;subdiv.render_levels=2 + tex=bpy.data.textures.new(obj.name+'_Microrelief',type='CLOUDS') + tex.noise_scale=.012;tex.noise_depth=2 + displace=obj.modifiers.new('HIGH RES · sculpted microrelief','DISPLACE') + displace.texture=tex;displace.strength=.0018;displace.mid_level=.5 + + +def add_offline_materials(objects, project): + """Editable Blender PBR nodes; optional project maps, standalone-safe fallback. + + Runtime shaders remain Godot-authored. Blender sources use the same oak + height map where available, with procedural pores for the other surfaces. + Images are external resources, avoiding 33 duplicate copies of a 4K map. + """ + materials={m for o in objects if o.type=='MESH' for m in o.data.materials if m} + for mat in materials: + if mat.get('phase10_pbr') or not mat.name.startswith('SW_HD_'): continue + nodes=mat.node_tree.nodes;links=mat.node_tree.links + bsdf=nodes.get('Principled BSDF') + if not bsdf or bsdf.inputs['Emission Strength'].default_value>0: continue + coord=nodes.new('ShaderNodeTexCoord');coord.location=(-700,100) + grain=nodes.new('ShaderNodeTexNoise');grain.location=(-470,100) + grain.inputs['Scale'].default_value=65;grain.inputs['Detail'].default_value=4 + links.new(coord.outputs['Object'],grain.inputs['Vector']) + height=grain.outputs['Fac'] + is_bark=mat.name.startswith('SW_HD_W_') and any(k in mat.name for k in ['bark','wood','groove']) + path=project/'assets/materials/phase10/oak-height-4k.png' + if is_bark and path.exists(): + image=nodes.new('ShaderNodeTexImage');image.location=(-460,-150) + image.image=bpy.data.images.load(str(path),check_existing=True) + image.image.colorspace_settings.name='Non-Color' + image.projection='BOX';image.projection_blend=.25 + links.new(coord.outputs['Generated'],image.inputs['Vector']) + height=image.outputs['Color'] + bump=nodes.new('ShaderNodeBump');bump.location=(-120,-80) + bump.inputs['Strength'].default_value=.32 if is_bark else .16 + bump.inputs['Distance'].default_value=.018 if is_bark else .009 + links.new(height,bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) + mat['phase10_pbr']=True + +from math import pi, sin, cos +import bpy +import hashlib + + +def g_legs(m, spread=.28, height=.40, lean=0, slim=False): + """Bent stone legs, joint rings and two separate forward toes.""" + for s,side in [(-1,'L'),(1,'R')]: + ankle=(s*spread,-.015,.14) + knee=(s*spread*1.1,.03+lean,height*.61) + hip=(s*spread*.72,.06,height) + radius=.075 if slim else .155 + r_band('Leg'+side+'_Thigh',hip,knee,radius,m['primary'],6) + r_band('Leg'+side+'_Shin',knee,ankle,radius*.9,m['primary'],6) + r_rock('Leg'+side+'_Knee',knee,(radius*1.2,radius,radius*1.1),m['primary'],s*.2) + r_disc('Leg'+side+'_Joint',(knee[0],knee[1]-.085,knee[2]),radius*.60,.06,m['accent']) + r_band('Leg'+side+'_AnkleBand',(ankle[0],ankle[1],.10),(ankle[0],ankle[1],.17),radius*1.1,m['accent']) + for j in range(2): + x=ankle[0]+(j-.5)*(.12 if slim else .15) + r_block('Leg'+side+'_Toe'+str(j),(x,-.11,.065),(.13 if slim else .18,.34,.13),m['primary']) + + +def g_arm(name, shoulder, elbow, hand, m, radius=.16, gold=True): + r_rock(name+'_Shoulder',shoulder,(radius*1.40,radius*1.24,radius*1.36),m['primary'],.23) + r_band(name+'_Upper',shoulder,elbow,radius,m['primary'],7) + r_rock(name+'_Elbow',elbow,(radius*1.12,)*3,m['primary'],.7) + r_band(name+'_Lower',elbow,hand,radius*1.1,m['primary'],7) + if gold: + a=tuple(elbow[i]*.35+hand[i]*.65 for i in range(3)) + b=tuple(elbow[i]*.15+hand[i]*.85 for i in range(3)) + r_band(name+'_Cuff',a,b,radius*1.24,m['accent'],8) + r_rock(name+'_Hand',hand,(radius*1.35,radius*1.2,radius*1.25),m['primary'],-.4) + + +def g_coal(up,m): + """Wide jaw-dominated rock creature, short legs, hanging claws and a crest.""" + g_legs(m,.26,.40) + r_rock('Body_MoltenCore',(0,.02,.73),(.43,.30,.50),m['secondary'],.16) + r_rock('Body_BackRock',(0,.15,.79),(.46,.27,.46),m['primary'],.37) + # A real wide mouth is framed by stone teeth, rather than a separate white face. + jaw=[(-.36,.10),(-.28,.20),(-.16,.16),(0,.23),(.17,.14),(.30,.18),(.38,.06), + (.29,-.18),(.16,-.09),(.02,-.23),(-.13,-.10),(-.29,-.19)] + r_plate('Head_GlowingJaw',(0,-.298,.75),jaw,.045,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + brow=[(-.20,-.04),(-.04,.02),(.19,-.12),(.20,.17),(-.04,.22),(-.19,.11)] + r_plate('Head_Brow'+side,(s*.19,-.335,.97),[(s*x,z) for x,z in brow],.16,m['primary'],.06) + r_sweep('Head_Eye'+side,[(s*.29,-.431,.92),(s*.11,-.434,.95)],[.015,.024],m['secondary'],4) + r_rock('Head_Cheek'+side,(s*.34,-.19,.73),(.19,.18,.27),m['primary'],s*.28) + for j in range(3): + x=s*(.07+j*.095) + r_sweep('Head_UpperFang'+side+str(j),[(x,-.39,.95-j*.022),(x+s*.018,-.408,.79-j*.036)], + [.069,0],m['primary'],4) + r_sweep('Head_LowerFang'+side+str(j),[(x,-.315,.49+j*.025),(x,-.395,.65+j*.035)], + [.075,0],m['primary'],4) + sh=(s*.45,.01,.91) + elbow=(s*.58,-.045,.66) + hand=(s*(.65 if up else .59),-.18,.46) + g_arm('Arm'+side,sh,elbow,hand,m,.145,up) + r_rock('Arm'+side+'_GoldPlate',(s*.47,-.08,1.035),(.105,.08,.13),m['accent']) + for j in range(2): + x=hand[0]+(j-.5)*.18 + if up: + points=[(x,-.245,.57),(x+s*.04,-.42,.46),(x+s*.03,-.52,.27),(x-s*.065,-.48,.15)] + radii=[.12,.12,.065,0] + else: + points=[(x,-.245,.51),(x+s*.025,-.36,.43),(x+s*.01,-.42,.30),(x-s*.025,-.40,.24)] + radii=[.075,.07,.038,0] + r_sweep('Weapon'+side+'_Claw'+str(j),points,radii,m['accent'],6) + if up: + r_sweep('Body_ShoulderHorn'+side,[(s*.40,.03,1.03),(s*.53,.03,1.24),(s*.46,.02,1.33)], + [.15,.09,0],m['primary'],5) + crest=[(0,.15,1.14),(0,.13,1.34 if up else 1.29),(0,.08,1.47 if up else 1.34)] + r_sweep('Head_CragCrown',crest,[.22,.12,0],m['primary'],5) + r_rock('Head_CrownGold',(0,-.055,1.19),(.075,.055,.115),m['accent']) + if up: + for s in [-1,1]: + r_sweep('Body_DorsalSpire'+str(s),[(s*.20,.21,1.11),(s*.26,.21,1.42)], + [.13,0],m['primary'],5) + + +def g_tower(name,loc,size,m,slots=2): + """Solid shoulder fortress with true separated crenellations.""" + x,y,z=loc + w,d,h=size + r_block(name+'_Keep',loc,size,m['primary']) + r_block(name+'_GoldBelt',(x,y,z-h*.28),(w*1.04,d*1.04,.065),m['accent'],.08) + for j in range(slots): + bx=x+(j-(slots-1)/2)*w*.42 + box(name+'_Window'+str(j),(bx,y-d*.5-.041,z),(.037,.017,h*.32),m['secondary']) + for j,(dx,dy) in enumerate([(-1,-1),(1,-1),(-1,1),(1,1)]): + r_block(name+'_Merlon'+str(j),(x+dx*w*.34,y+dy*d*.31,z+h*.56), + (w*.26,d*.38,h*.34),m['primary'],.04) + + +def g_tank(up,m): + g_legs(m,.29,.42) + r_block('Body_StoneMass',(0,.04,.85),(.84,.54,.94),m['primary']) + shield=[(-.38,.47),(.38,.47),(.39,-.26),(0,-.51),(-.39,-.26)] + r_plate('Body_TowerShield_Rim',(0,-.29,.82),shield,.15,m['accent']) + r_plate('Body_TowerShield_Face',(0,-.375,.82),[(x*.90,z*.94) for x,z in shield],.045,m['primary'],.065) + # Vertical furnace slit is the focal mark of both icons. + sigil=[(-.035,.30),(.035,.30),(.035,-.08),(0,-.13),(-.035,-.08)] + r_plate('Head_VerticalEmber',(0,-.466,1.00),sigil,.025,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + r_band('Body_ShieldLine'+side,(s*.065,-.457,.69),(s*.065,-.457,1.22),.021,m['accent'],4) + g_arm('Arm'+side,(s*.48,.035,1.03),(s*.59,.03,.73),(s*.63,-.13,.47),m,.19) + if up: + g_tower('Arm'+side+'_Castle',(s*.48,.035,1.12),(.42,.47,.37),m) + g_tower('Arm'+side+'_Bastion',(s*.61,-.07,.65),(.30,.39,.30),m,1) + else: + r_block('Arm'+side+'_ShoulderGold',(s*.48,-.04,1.13),(.35,.37,.12),m['accent']) + if up: + g_tower('Head_CentralKeep',(0,.06,1.37),(.30,.32,.37),m,1) + r_block('Body_ShieldRidge',(0,-.45,.85),(.08,.045,.95),m['accent'],.05) + r_plate('Body_ShieldEmber',(0,-.482,1.01),[(-.022,.17),(.022,.17),(.022,-.14),(0,-.18),(-.022,-.14)],.02,m['secondary']) + + +def g_lancer(m): + g_legs(m,.235,.69,.12,True) + r_plate('Body_Cuirass',(0,.02,.98),[(-.24,.19),(.24,.19),(.15,-.13),(0,-.29),(-.15,-.13)],.26,m['primary'],.06) + r_inset('Body_ChestCleft',(0,-.145,.98),[(-.10,.17),(.08,.17),(.035,-.20),(-.01,-.25)],.025,m['accent'],m['secondary']) + r_band('Head_Neck',(0,.02,1.13),(0,-.04,1.38),.078,m['primary'],5) + r_plate('Head_SpearHelm',(0,-.045,1.42),[(-.16,.08),(0,.02),(.16,.10),(.065,-.04),(0,-.19),(-.065,-.04)],.16,m['accent'],.035) + r_plate('Head_EmberVisor',(0,-.148,1.33),[(-.04,.05),(.055,.05),(0,-.15)],.03,m['secondary']) + r_sweep('Head_HelmCrest',[(0,.00,1.43),(-.035,.10,1.66)],[.085,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.245,0,1.14) + hand=(s*.28,-.25,.91) + r_band('Arm'+side+'_Upper',sh,(s*.34,-.04,.95),.067,m['primary'],5) + r_band('Arm'+side+'_Forearm',(s*.34,-.04,.95),hand,.067,m['primary'],5) + r_rock('Arm'+side+'_Hand',hand,(.075,.065,.075),m['primary']) + r_plate('Arm'+side+'_Pauldron',(s*.27,0,1.17),[(s*-.095,-.07),(s*.17,-.04),(s*.075,.10)],.16,m['accent']) + # Long reinforced lance runs across both hands, held at waist height. + start=(-.66,-.23,.94) + end=(.60,-.30,.94) + r_band('Weapon_LanceCore',start,end,.065,m['primary'],8) + for j in range(5): + t=.10+j*.19 + p=tuple(start[i]*(1-t)+end[i]*t for i in range(3)) + q=(p[0]+.038,p[1]-.002,p[2]) + r_band('Weapon_LanceCollar'+str(j),p,q,.086,m['accent'],8) + r_sweep('Weapon_GlassSpearhead',[end,(.73,-.307,.94),(.98,-.32,.94)],[.10,.13,0],m['secondary'],4) + + +def g_ballista(m): + """Headless two-legged siege crossbow, matching the G06 image silhouette.""" + g_legs(m,.32,.57,.12) + r_block('Body_BallistaChassis',(0,.05,.64),(.48,.48,.34),m['primary']) + r_block('Weapon_Rail',(0,-.05,.90),(.21,1.05,.20),m['primary']) + r_block('Weapon_RearHousing',(0,.44,.98),(.32,.32,.27),m['primary']) + box('Weapon_EmberRail',(0,-.10,1.01),(.07,1.08,.023),m['secondary']) + for i,y in enumerate([-.54,-.17,.33]): + r_block('Weapon_RailCollar'+str(i),(0,y,.92),(.26,.065,.245),m['accent'],.08) + for s,side in [(-1,'L'),(1,'R')]: + bow=[(s*.12,-.40,.94),(s*.39,-.43,.92),(s*.70,-.24,.96),(s*.81,.04,1.03)] + r_sweep('Weapon_GlassLimb'+side,bow,[.115,.14,.105,.065],m['secondary'],5) + r_band('Weapon_BowBinding'+side,(s*.16,-.42,.92),(s*.22,-.42,.92),.15,m['accent'],6) + r_band('Weapon_Drawstring'+side,bow[-1],(0,.45,1.03),.014,m['primary'],4) + r_disc('Body_Crank'+side,(s*.20,-.13,.69),.13,.07,m['accent']) + r_disc('Body_CrankInset'+side,(s*.20,-.175,.69),.09,.025,m['primary']) + r_sweep('Weapon_CrystalBolt',[(0,-.54,.99),(0,-.68,.99),(0,-.96,.99)],[.06,.10,0],m['secondary'],4) + + +def g_mortar(up,m): + """Huge bowl torso on squat stone legs; upgrade widens the magma crater.""" + g_legs(m,.29,.41) + r_rock('Body_Foundation',(0,.035,.55),(.41,.29,.29),m['primary']) + radius=.52 if up else .45 + axis=(0,-.24,.97) + r_lathe('Body_Mortar',(0,.08,.54),[(0,0),(.25,.02),(radius*.90,.29),(radius,.65), + (radius*.84,.65),(radius*.73,.28),(0,.13)],m['primary'],axis,12) + # Wide gold lip, open centre and visible lower ember bed. + r_lathe('Body_MortarRim',(0,.08,.54),[(radius*1.018,.57),(radius*1.035,.663), + (radius*.815,.663),(radius*.81,.60)],m['accent'],axis,12) + r_lathe('Weapon_LavaPool',(0,-.015,.99 if up else .91),[(0,0),(.36 if up else .23,0), + (.36 if up else .23,.035),(0,.035)],m['secondary'],axis,12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.45,.05,.95),(s*.59,-.03,.70),(s*.46,-.27,.53),m,.17) + r_block('Body_RimClasp'+side,(s*radius*.71,-.26,1.16),(.11,.16,.16),m['accent']) + if up: + r_inset('Body_FrontSigil',(0,-.44,.96),[(-.14,.19),(.14,.19),(.06,-.15),(0,-.20),(-.06,-.15)],.065,m['accent'],m['secondary']) + for k in range(4): + a=k*pi/2+.3 + r_rock('Weapon_LavaRock'+str(k),(.23*cos(a),-.015+.20*sin(a),1.025),(.09,.085,.04),m['primary']) + else: + r_rock('Weapon_EmberBoulder',(0,-.02,.91),(.19,.16,.18),m['secondary'],.2) + + +def g_hearth(up,m): + """Broad oven body with cream hood; no human head. Upgrade has a sun core.""" + g_legs(m,.28,.42) + r_rock('Body_StoneBack',(0,.10,.85),(.45,.30,.53),m['primary']) + # Arched opening is a thick half-ring and two pillars, not a forward horn. + if not up: + pts=[(.34*cos(pi*k/10),-.11,1.03+.34*sin(pi*k/10)) for k in range(11)] + r_sweep('Body_CeramicArch',pts,[.105]*len(pts),m['light'],6) + for s in [-1,1]: + r_block('Body_CeramicPillar'+str(s),(s*.34,-.12,.89),(.19,.25,.36),m['light']) + r_block('Head_Chimney',(0,.075,1.39),(.37,.35,.22),m['light']) + r_block('Head_ChimneyShadow',(0,-.109,1.37),(.23,.025,.11),m['primary']) + else: + r_rock('Body_SunCore',(0,-.22,1.13),(.23,.09,.25),m['secondary']) + ring('Body_SunHalo',(0,-.19,1.17),.35,.045,m['accent'],rotation=(pi/2,0,0),segments=12) + for k in range(7): + a=pi*k/6 + r_sweep('Body_HaloRay'+str(k),[(.34*cos(a),-.15,1.17+.34*sin(a)), + (.49*cos(a),-.14,1.17+.49*sin(a))],[.065,0],m['accent'],4) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CeramicMantle'+side,(s*.42,.06,.90),[(s*-.06,.38),(s*.14,.30),(s*.20,-.24),(s*.11,-.40),(s*-.08,-.21)],.27,m['light']) + r_plate('Body_CeramicTabard'+side,(s*.49,-.06,.39),[(s*-.08,.23),(s*.08,.25),(s*.14,-.21),(s*.04,-.29),(s*-.10,-.20)],.04,m['light']) + bowl_z=.64 + r_lathe('Weapon_HearthBowl',(0,-.39,bowl_z-.16),[(0,0),(.17,.02),(.37 if up else .30,.17), + (.39 if up else .32,.23),(.33 if up else .26,.23),(.23,.10),(0,.08)],m['accent'],segments=12) + cylinder('Weapon_EmberBed',(0,-.39,bowl_z+.015),.30 if up else .23,.028,m['secondary'],vertices=12) + for s,side in [(-1,'L'),(1,'R')]: + g_arm('Arm'+side,(s*.41,.015,1.03),(s*.54,-.13,.76),(s*.36,-.40,.61),m,.17) + r_disc('Arm'+side+'_Sigil',(s*.46,-.16,1.01),.12,.045,m['accent']) + for k,(x,z) in enumerate([(-.12,.26),(.06,.40),(.18,.20)]): + r_sweep('Weapon_Flame'+str(k),[(x,-.39,bowl_z),(x-.045,-.37,bowl_z+z*.42), + (x+.025,-.35,bowl_z+z*.78),(x-.04,-.36,bowl_z+z)], + [.07,.09,.045,0],m['secondary'],5) + if up: + r_sweep('Body_SolarStream',[(0,-.29,1.00),(.03,-.38,.85),(0,-.39,.70)], + [.06,.05,.055],m['secondary'],5) + r_sun('Weapon_BowlSun',(0,-.69,.66),.095,m) + + +def build_glutpakt(spec,m): + role=spec['role'] + up=spec['upgraded'] + if role=='melee': g_coal(up,m) + elif role=='tank': g_tank(up,m) + elif role=='ranged': g_ballista(m) if up else g_lancer(m) + elif role=='artillery': g_mortar(up,m) + elif role=='support': g_hearth(up,m) + else: raise ValueError('Unknown Glutpakt role: '+role) + finish_glutpakt_surfaces(m) + + +def finish_glutpakt_surfaces(m): + """Stable basalt/gold facet values, matching the chipped stone in the icons. + + Material changes only: retain the original solid geometry and triangle cap. + Each editable face keeps a material slot; no image projection or randomness. + """ + for key, factors in [('primary', (.78, 1.0, 1.32, 1.65)), ('accent', (.76, 1.0, 1.25))]: + original = m[key] + palette = [] + for index, factor in enumerate(factors): + mat = original.copy() + mat.name = original['material_name'] + '_Facet' + str(index) + mat['material_name'] = mat.name + base = list(original.diffuse_color) + base[:3] = [min(1.0, v * factor) for v in base[:3]] + mat.diffuse_color = base + mat.node_tree.nodes.get('Principled BSDF').inputs['Base Color'].default_value = base + palette.append(mat) + for obj in bpy.context.scene.objects: + if obj.type != 'MESH' or not obj.data.materials or obj.data.materials[0] != original: + continue + obj.data.materials.clear() + for mat in palette: + obj.data.materials.append(mat) + seed = int(hashlib.sha256(obj['part_name'].encode()).hexdigest()[:8], 16) + for face in obj.data.polygons: + # Slightly brighter upward facets, varied side facets. + face.material_index = min(len(palette)-1, (seed + face.index * 7) % len(palette)) + +from math import sin, cos, pi + + +def n_ribbon(name,points,widths,mat): + if name.startswith('Head_ChoirHorn'): + return r_sweep(name,points,widths,mat,6,ribbon=True) + # One interpolated section per span gives flowing curves instead of zigzag rods. + from mathutils import Vector + refined=[]; radii=[] + for i in range(len(points)-1): + p0=Vector(points[max(i-1,0)]); p1=Vector(points[i]) + p2=Vector(points[i+1]); p3=Vector(points[min(i+2,len(points)-1)]) + for t in (0,.5): + p=.5*((2*p1)+(-p0+p2)*t+(2*p0-5*p1+4*p2-p3)*t*t+(-p0+3*p1-3*p2+p3)*t*t*t) + refined.append(tuple(p)); radii.append(widths[i]*(1-t)+widths[i+1]*t) + refined.append(points[-1]);radii.append(widths[-1]) + return r_sweep(name,refined,radii,mat,6,ribbon=True) + + +def n_mask(name,loc,scale,m,singing=False): + x,y,z=loc + outline=[(-.12,.14),(-.05,.24),(.055,.22),(.145,.11),(.12,-.075),(0,-.24),(-.12,-.08)] + r_plate(name,loc,[(a*scale,b*scale) for a,b in outline],.09*scale,m['light'],.055*scale) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.065*scale,y-.091*scale,z+.025*scale), + [(s*-.032*scale,.005*scale),(s*.030*scale,.027*scale),(s*.027*scale,-.014*scale),(s*-.019*scale,-.040*scale)], + .012,m['accent'],.003) + if singing: + r_rock(name+'_Mouth',(x,y-.092*scale,z-.09*scale),(.035*scale,.018*scale,.061*scale),m['primary']) + + +def n_wisps(m,wide=False,tall=False): + """Tapering curved ribbons replace human legs and the rigid cone skirt.""" + top=1.16 if tall else .90 + narrow=.55 if tall and not wide else 1 + for s,side in [(-1,'L'),(1,'R')]: + spread=.28 if wide else .16 + pts=[(s*spread,.08,top),(s*.08,.06,top*.75),(s*.20,.025,top*.54), + (s*.075,0,top*.34),(s*.20,-.015,top*.17),(s*.26,-.025,.055),(s*.36,-.025,.075)] + n_ribbon('Body_Wisp'+side,pts,[v*narrow for v in [.15 if wide else .11,.18,.14,.085,.048,.03,0]],m['secondary']) + pts2=[(s*.16,.16,top*.86),(s*.33,.10,top*.64),(s*.18,.07,top*.39), + (s*.35,.03,.20),(s*.30,.015,.08),(s*.22,0,.01)] + n_ribbon('Body_Tail'+side,pts2,[v*narrow for v in [.09,.105,.085,.057,.025,0]],m['primary']) + n_ribbon('Body_CentralFlow',[(0,.06,top),(-.10,-.055,top*.73),(.13,-.11,top*.46),(-.04,-.09,top*.19),(.07,-.08,.12)], + [v*narrow for v in [.18,.24 if wide else .16,.16,.045,0]],m['primary']) + + +def n_hood(m,up=False,z=1.22): + n_mask('Head_Mask',(0,-.15,z),1.0,m) + n_ribbon('Head_CurledHood',[(.14,.045,z-.10),(.09,.06,z+.15),(-.10,.04,z+.28), + (-.22,.015,z+.31),(-.25,0,z+.42),(-.15,-.01,z+.43)], + [.18,.17,.13,.075,.04,0],m['secondary']) + + +def n_crescent(name,loc,scale,m,light=True,flip=1): + x,y,z=loc + pts=[(x-flip*.13*scale,y,z+.17*scale),(x-flip*.17*scale,y,z), + (x-flip*.045*scale,y-.01,z-.14*scale),(x+flip*.15*scale,y-.02,z-.13*scale), + (x+flip*.23*scale,y-.02,z-.025*scale)] + n_ribbon(name,pts,[0,.085*scale,.10*scale,.06*scale,0],m['light'] if light else m['secondary']) + + +def n_tank(up,m): + n_wisps(m,up) + n_hood(m,up,1.20 if up else 1.14) + for k in range(3): + z=.89-k*.16 + w=(.40 if up else .27)-k*.045 + outline=[(-w,.10),(0,.045),(w,.10),(w*.65,-.11),(0,-.21),(-w*.65,-.11)] + # Each layer is a thick wrapped plate, with a light inner leading edge. + r_plate('Body_WrappedArmor'+str(k),(0,-.12,z),outline,.26,m['light'] if up and k%2==0 else m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.19,.04,1.02),(s*.32,0,.94),(s*.38,-.06,.75)], + [.11,.13,.08],m['secondary']) + if up: + n_ribbon('Arm'+side+'_GreatShield',[(s*.29,-.12,.67),(s*.51,-.08,.81), + (s*.48,-.05,1.13),(s*.37,-.01,1.39)], + [0,.19,.18,0],m['light']) + n_ribbon('Arm'+side+'_ShieldInlay',[(s*.35,-.145,.74),(s*.48,-.12,.90),(s*.43,-.09,1.15)], + [0,.11,0],m['secondary']) + else: + n_crescent('Weapon'+side+'_Claw',(s*.33,-.09,.79),.82,m,flip=s) + + +def n_dancer(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.31) + for s,side in [(-1,'L'),(1,'R')]: + high=(s<0 and not up) + tip=(s*.46,-.15,1.49 if high else .87) + n_ribbon('Arm'+side,[(s*.12,.025,1.12),(s*.31,.015,1.20 if high else 1.02),tip], + [.085,.10,.055],m['secondary']) + if not up: + r_sweep('Weapon'+side+'_Sickle',[tip,(tip[0]+s*.12,-.17,tip[2]-.12), + (tip[0]+s*.11,-.19,tip[2]-.28)],[.045,.045,0],m['light'],5) + if up: + pivot=(.27,-.25,.94) + r_rock('Weapon_ShearPivot',pivot,(.065,.04,.065),m['accent']) + for s,side in [(-1,'Lower'),(1,'Upper')]: + n_ribbon('Weapon_Shear'+side,[pivot,(.48,-.25,.94+s*.16),(.70,-.21,.94+s*.24),(.78,-.17,.94+s*.40)], + [.045,.115,.095,0],m['light']) + pts=[(.22,-.245,.94),(.01,-.24,.94+s*.14),(-.16,-.21,.94+s*.10), + (-.15,-.20,.94-s*.045),(.02,-.225,.94-s*.02),(.20,-.245,.94)] + n_ribbon('Weapon_ShearLoop'+side,pts,[.025,.035,.035,.035,.035,.025],m['light']) + n_ribbon('Head_CrescentCrown',[(.04,.03,1.44),(-.10,.02,1.64),(-.04,0,1.76)], + [.095,.105,0],m['light']) + + +def n_horn(name,loc,radius,depth,m,axis): + r_lathe(name,loc,[(0,0),(.035,.015),(.048,depth*.42),(radius*.55,depth*.78), + (radius,depth),(radius*.82,depth),(radius*.42,depth*.78),(.022,depth*.30),(0,depth*.29)], + m['light'],axis,10) + from mathutils import Vector + lip=Vector(loc)+Vector(axis).normalized()*depth + r_lathe(name+'_MintLip',lip,[(radius*1.015,-.025),(radius*1.025,.01), + (radius*.80,.01),(radius*.80,-.025)],m['accent'],axis,10) + + +def n_ranged(up,m): + n_wisps(m,False,True) + n_hood(m,up,1.29) + if up: + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.14,0,1.06),(s*.28,-.16,.97),(s*.43,-.20,1.04)], + [.09,.10,.025],m['light']) + n_ribbon('Weapon_HornArch'+side,[(s*.14,.09,1.24),(s*.28,.10,1.48), + (s*.45,.05,1.49),(s*.55,-.05,1.32)], + [.14,.13,.115,.08],m['secondary']) + n_horn('Weapon_Horn'+side,(s*.54,-.025,1.36),.23,.43,m,(s*.28,-.8,-.35)) + else: + n_horn('Weapon_MouthHorn',(.025,-.25,1.24),.13,.60,m,(1,-.22,-.03)) + n_ribbon('ArmL',[(-.18,0,1.06),(-.23,-.17,1.10),(.16,-.25,1.19)], + [.10,.095,.035],m['light']) + n_ribbon('ArmR',[(.15,0,1.07),(.30,-.12,1.02),(.38,-.27,1.19)], + [.09,.10,.025],m['secondary']) + + +def n_bell(up,m): + if up: + n_wisps(m,True) + r_arch_shell('Body_CathedralShell',(0,.045,0),[(.13,1.48),(.22,1.15),(.43,.58),(.48,.48), + (.43,.45),(.35,.60),(.15,1.17),(.085,1.48)],m['secondary']) + ring('Body_BellSkirt',(0,.045,.49),.46,.055,m['light'],segments=14) + arch=[(-.38,-.13,.54),(-.29,-.115,.98),(-.12,-.05,1.34),(0,-.01,1.45), + (.12,-.05,1.34),(.29,-.115,.98),(.38,-.13,.54)] + n_ribbon('Body_CathedralFrontArch',arch,[.035]*len(arch),m['light']) + beam('Weapon_ClapperChain',(0,-.055,1.27),(0,-.075,.84),.016,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.075,.80),(.125,.11,.15),m['accent']) + n_mask('Body_ArchMask',(0,-.07,1.22),.48,m) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Head_Spire'+side,[(s*.17,.055,1.27),(s*.28,.055,1.53), + (s*.24,.05,1.69)],[.085,.07,0],m['light']) + n_crescent('Arm'+side+'_Sickle',(s*.43,0,.89),1,m,flip=s) + n_ribbon('Head_CentralSpire',[(0,.05,1.42),(-.025,.06,1.71),(.02,.02,1.83)], + [.10,.065,0],m['light']) + else: + n_wisps(m,True) + n_hood(m,False,1.39) + axis=(0,-.85,-.40) + r_lathe('Weapon_HangingBell',(0,.03,1.15),[(0,0),(.16,.02),(.22,.14),(.28,.42),(.44,.68), + (.45,.73),(.38,.73),(.23,.43),(.16,.15),(0,.12)],m['secondary'],axis,12) + from mathutils import Vector + lip=Vector((0,.03,1.15))+Vector(axis).normalized()*.70 + r_lathe('Weapon_BellRim',lip,[(.455,0),(.46,.045),(.375,.045),(.375,0)],m['light'],axis,12) + beam('Weapon_ClapperStem',(0,-.08,1.10),(0,-.55,.80),.018,m['accent'],vertices=6) + r_rock('Weapon_Clapper',(0,-.56,.78),(.10,.085,.115),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,.07,1.21),(s*.41,.02,1.13), + (s*.36,-.26,1.02),(s*.23,-.30,1.12)], + [.13,.15,.11,.02],m['secondary']) + + +def n_singer(up,m): + n_wisps(m,up,True) + n_hood(m,up,1.33) + # Singing mask has an open mouth, and floating masks have their own wisps. + r_rock('Head_SingingMouth',(0,-.248,1.23),(.035,.018,.061),m['primary']) + for k in range(2): + r_plate('Body_ChoirCollar'+str(k),(0,-.115,1.08-k*.13),[(-.25,.12),(0,.045),(.25,.12),(.17,-.045),(0,-.14),(-.17,-.045)], + .17,m['light'] if k==0 else m['secondary']) + r_rock('Body_ChoirGem',(0,-.225,.93),(.065,.045,.105),m['accent']) + for s,side in [(-1,'L'),(1,'R')]: + n_ribbon('Arm'+side,[(s*.18,0,1.04),(s*.32,-.035,.91),(s*.40,-.11,1.02)], + [.11,.12,.05],m['secondary']) + n_crescent('Arm'+side+'_Cuff',(s*.41,-.10,1.04),1,m,flip=-s) + floating=[(.42,.06,1.52)] if not up else [(-.40,.09,1.53),(.38,.08,1.50),(.28,.16,1.86)] + for k,loc in enumerate(floating): + x,y,z=loc + n_mask('Head_ChoirMask'+str(k),loc,.60,m,True) + n_ribbon('Head_ChoirWisp'+str(k),[(x,y,z-.08),(x-.055,y+.025,z-.20),(x+.02,y,z-.27)], + [.06,.04,0],m['secondary']) + for s in [-1,1]: + n_ribbon('Head_ChoirHorn'+str(k)+'_'+str(s),[(x+s*.06,y+.02,z+.09), + (x+s*.13,y+.02,z+.20),(x+s*.09,y,z+.25)],[.045,.045,0],m['light']) + if up: + for s in [-1,1]: + n_ribbon('Head_GreatHorn'+str(s),[(s*.10,.06,1.46),(s*.23,.04,1.65),(s*.16,0,1.79)], + [.09,.08,0],m['light']) + + +def build_nebelchor(spec,m): + role=spec['role']; up=spec['upgraded'] + {'tank':n_tank,'melee':n_dancer,'ranged':n_ranged,'artillery':n_bell,'support':n_singer}[role](up,m) + +from math import sin, cos, pi + + +def m_joint(name,loc,radius,m): + r_disc(name,loc,radius,.065,m['secondary']) + r_disc(name+'_Pin',(loc[0],loc[1]-.04,loc[2]),radius*.55,.026,m['accent']) + + +def m_legs(m,tall=False,wide=False,four=False): + height=.73 if tall else .43 + spread=.27 if wide else .20 + for k in range(4 if four else 2): + s=-1 if k%2==0 else 1 + y=.29 if k>1 else -.045 + x=s*spread + hip=(x*.68,y+.045,height) + knee=(x*1.22,y+.09,height*.58) + ankle=(x,y,.11) + side=str(k) + r_band('Leg'+side+'_Piston',hip,knee,.055 if tall else .085,m['accent'],6) + r_band('Leg'+side+'_Shin',knee,ankle,.048 if tall else .07,m['accent'],6) + m_joint('Leg'+side+'_Knee',(knee[0],knee[1]-.02,knee[2]),.065 if tall else .09,m) + r_plate('Leg'+side+'_ThighArmor',(hip[0],y-.022,height*.82), + [(-.07,.12),(.07,.10),(.035,-.12),(-.045,-.09)],.08,m['light']) + r_plate('Leg'+side+'_Greave',(x,y-.045,height*.35), + [(-.055,.12),(.07,.15),(.035,-.16),(-.045,-.09)],.07,m['primary']) + for j in range(2): + toe=(x+(j-.5)*.095,y-.16,.02) + r_sweep('Leg'+side+'_Toe'+str(j),[(x+(j-.5)*.04,y,.095),toe],[.065,0],m['accent'],5) + r_band('Leg'+side+'_AnkleGold',(x,y,.10),(x,y,.15),.067,m['secondary'],8) + + +def m_face(name,loc,m,round_face=False,tall=False): + x,y,z=loc + if round_face: + r_disc(name+'_BrassFrame',loc,.145,.055,m['secondary']) + r_disc(name+'_Ceramic',(x,y-.038,z),.118,.035,m['light']) + for s in [-1,1]: + r_disc(name+'_Eye'+str(s),(x+s*.051,y-.065,z+.027),.027,.015,m['accent']) + box(name+'_Mouth',(x,y-.068,z-.048),(.068,.012,.013),m['accent']) + else: + r_plate(name+'_Face',loc,[(-.09,.10),(.085,.10),(.074,-.03),(0,-.15),(-.076,-.025)],.09,m['light']) + for s in [-1,1]: + r_plate(name+'_Eye'+str(s),(x+s*.04,y-.075,z+.016),[(-.023,.01),(.023,.01),(0,-.013)],.012,m['accent']) + if tall: + r_plate(name+'_Crest',(x,y+.035,z+.12),[(-.11,-.05),(.10,-.04),(-.04,.24)],.10,m['primary']) + + +def m_torso(m,up=False,z=.98): + outline=[(-.22,.20),(.22,.20),(.14,-.04),(0,-.30),(-.14,-.04)] + r_inset('Body_Breastplate',(0,.025,z),outline,.25,m['secondary'],m['primary']) + r_band('Body_Waist',(0,.03,z-.30),(0,.03,z-.12),.085,m['accent'],8) + for s,side in [(-1,'L'),(1,'R')]: + m_joint('Arm'+side+'_Shoulder',(s*.22,.015,z+.11),.078,m) + r_plate('Body_HipPlate'+side,(s*.16,.04,z-.26),[(s*-.07,.13),(s*.08,.07),(s*.12,-.14),(0,-.10)],.09,m['light']) + + +def m_boiler(up,m): + m_legs(m,False,True) + if not up: + ellipsoid('Body_RoundKettle',(0,.04,.83),(.40,.31,.43),m['primary'],subdivisions=2) + ring('Body_Belt',(0,.04,.64),.335,.036,m['secondary'],segments=12) + m_face('Head',(0,-.27,.99),m,True) + r_disc('Body_PressureGauge',(-.22,-.24,.86),.095,.035,m['secondary']) + r_disc('Body_GaugeFace',(-.22,-.266,.86),.071,.018,m['light']) + r_band('Body_GaugeNeedle',(-.22,-.28,.86),(-.19,-.28,.90),.009,m['accent'],4) + r_lathe('Body_Chimney',(-.15,.09,1.14),[(.075,0),(.075,.23),(.053,.23),(.053,.025)],m['accent'],segments=8) + ring('Body_ChimneyLip',(-.15,.09,1.37),.076,.018,m['secondary'],segments=8) + else: + r_block('Body_HeavyChest',(0,.04,.89),(.65,.45,.60),m['primary']) + r_inset('Body_CeramicChest',(0,-.22,.89),[(-.13,.27),(.13,.27),(.11,-.20),(0,-.25),(-.11,-.20)],.09,m['secondary'],m['light']) + m_face('Head',(0,-.005,1.28),m) + for s,side in [(-1,'L'),(1,'R')]: + cylinder('Body_PressureTank'+side,(s*.30,.16,1.20),.14,.47,m['light'],vertices=10) + for z in [1.00,1.40]: + cylinder('Body_TankBand'+side+str(z),(s*.30,.16,z),.155,.05,m['accent'],vertices=10) + cylinder('Body_ValveStem'+side,(s*.30,.16,1.50),.025,.13,m['secondary'],vertices=6) + ring('Body_ValveWheel'+side,(s*.30,.16,1.56),.07,.016,m['secondary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + sh=(s*.40,.04,.98); elbow=(s*.48,-.035,.73); hand=(s*.46,-.14,.57) + r_band('Arm'+side+'_Upper',sh,elbow,.075,m['accent'],8) + r_band('Arm'+side+'_Forearm',elbow,hand,.10,m['accent'],8) + m_joint('Arm'+side+'_Joint',(s*.40,-.075,.98),.13,m) + r_block('Arm'+side+'_Fist',hand,(.23,.23,.23),m['accent']) + r_band('Arm'+side+'_Cuff',(s*.46,-.11,.64),(s*.46,-.12,.59),.13,m['secondary'],8) + if up: + r_block('Arm'+side+'_Pauldron',(s*.40,.04,1.07),(.29,.38,.25),m['primary']) + r_inset('Arm'+side+'_Shield',(s*.49,-.16,.79),[(-.14,.23),(.14,.23),(.15,-.13),(0,-.23),(-.15,-.13)],.13,m['secondary'],m['primary'] if s>0 else m['light']) + + +def m_shear(up,m): + m_legs(m,True,up) + m_torso(m,up,1.02) + m_face('Head',(0,-.035,1.35),m,False,not up) + levels=[(1.20,1.57),(1.09,1.11),(.96,.71)] if up else [(1.16,1.00)] + for s,side in [(-1,'L'),(1,'R')]: + for k,(root_z,end_z) in enumerate(levels): + shoulder=(s*.18,.04,root_z) + elbow=(s*.39,.035,(root_z+end_z)/2) + wrist=(s*.58,-.06,end_z) + r_band('Arm'+side+str(k)+'_Rod',shoulder,elbow,.047,m['accent'],6) + r_band('Arm'+side+str(k)+'_Housing',elbow,wrist,.065,m['primary'],6) + m_joint('Arm'+side+str(k)+'_Pivot',(wrist[0],wrist[1]-.025,wrist[2]),.065,m) + directions=[.18] if up else [-.20,.20] + for j,dz in enumerate(directions): + points=[wrist,(s*.76,-.08,end_z+dz*.65),(s*.97,-.06,end_z+dz)] + r_sweep('Weapon'+side+str(k)+'_Blade'+str(j),points,[.040,.115,0],m['accent'],4,ribbon=True) + + +def m_crossbow(name,loc,width,length,m): + x,y,z=loc + r_block(name+'_Rail',loc,(.14,length,.11),m['accent']) + for s in [-1,1]: + points=[(x+s*.07,y-length*.27,z),(x+s*width*.33,y-length*.34,z), + (x+s*width*.50,y,z+.035)] + r_sweep(name+'_Bow'+str(s),points,[.065,.065,.025],m['accent'],5) + r_band(name+'_String'+str(s),points[-1],(x,y+length*.42,z+.025),.012,m['secondary'],4) + r_band(name+'_Bolt',(x,y+length*.35,z+.071),(x,y-length*.70,z+.071),.024,m['light'],5) + r_sweep(name+'_BoltTip',[(x,y-length*.60,z+.07),(x,y-length*.85,z+.07)],[.06,0],m['secondary'],4) + for j,yoff in enumerate([-.2,.15]): + r_block(name+'_Binding'+str(j),(x,y+yoff*length,z),(.19,.04,.15),m['secondary']) + + +def m_ranged(up,m): + m_legs(m,True,False,up) + m_torso(m,up,1.01) + m_face('Head',(0,-.025,1.37),m,False,True) + if not up: + r_disc('Head_Scope',(.073,-.094,1.39),.044,.055,m['secondary']) + for k in range(3): + r_band('Body_QuiverBolt'+str(k),(-.14+k*.055,.23,1.0),(-.14+k*.055,.23,1.43),.017,m['secondary'],5) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.23,-.23,1.07 if up else .88) + r_band('Arm'+side+'_Upper',(s*.23,.02,1.16),(s*.32,-.025,.97),.048,m['accent'],6) + r_band('Arm'+side+'_Lower',(s*.32,-.025,.97),hand,.063,m['primary'],6) + m_joint('Arm'+side+'_Wrist',hand,.048,m) + m_crossbow('Weapon_Crossbow',(0 if up else .27,-.26,1.11 if up else .89),1.25 if up else .48,.84 if up else .53,m) + + +def m_resonator(up,m): + m_legs(m,False,True,up) + r_block('Body_SiegeChassis',(0,.10,.62),(.64,.50,.31),m['primary']) + m_face('Head',(0,-.015,1.26 if up else 1.22),m,False,False) + centres=[-.31,.31] if up else [0] + for j,x in enumerate(centres): + # Body is the horizontal resonator, not a thin man carrying a trumpet. + axis=(0,-1,0) + r_lathe('Body_ResonatorHousing'+str(j),(x,.30,.91),[(0,0),(.26,0),(.29,.18),(.27,.46),(0,.46)],m['primary'],axis,12) + if up: + r_lathe('Weapon_ImpactDisc'+str(j),(x,-.17,.91),[(0,0),(.30,0),(.36,.08),(.34,.13),(.12,.16),(0,.16)],m['secondary'],axis,12) + r_band('Weapon_DiscPiston'+str(j),(x,-.28,.91),(x,-.48,.91),.075,m['accent'],8) + else: + r_lathe('Weapon_ResonatorBell',(x,-.09,.91),[(.13,0),(.17,.15),(.35,.42),(.40,.47),(.34,.47),(.12,.14),(0,.12),(0,0)],m['secondary'],axis,12) + r_band('Weapon_ResonatorPiston',(x,-.21,.91),(x,-.63,.91),.078,m['accent'],8) + for s in [-1,1]: + r_block('Body_HousingLatch'+str(j)+'_'+str(s),(x+s*.265,-.02,.91),(.065,.10,.19),m['secondary']) + + +def m_conductor(up,m): + m_legs(m,not up,False) + if up: + # Broad floor-length open coat, cream stole and large exposed pendulum. + r_lathe('Body_Coat',(0,.075,.12),[(0,0),(.50,0),(.20,.94),(.12,1.11),(0,1.11)],m['primary'],segments=8) + for s,side in [(-1,'L'),(1,'R')]: + r_plate('Body_CreamStole'+side,(s*.20,-.205,.84),[(-.065,.38),(.065,.38),(.11,-.40),(0,-.48),(-.055,-.37)],.035,m['light']) + r_band('Body_CoatGold'+side,(s*.10,-.26,1.17),(s*.45,-.26,.19),.02,m['secondary'],4) + r_plate('Body_PendulumOpening',(0,-.28,.76),[(-.09,.34),(.09,.34),(.13,-.34),(-.13,-.34)],.025,m['accent']) + r_band('Body_PendulumStem',(0,-.309,1.08),(0,-.309,.55),.022,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.325,.53),.13,.035,m['secondary']) + m_face('Head',(0,-.04,1.40),m) + for j,x in enumerate([-.12,0,.12]): + r_sweep('Head_Crown'+str(j),[(x,.025,1.48),(x*1.25,.025,1.78 if j==1 else 1.68)], + [.035,0],m['secondary'],4) + else: + m_torso(m,False,1.01) + m_face('Head',(0,-.025,1.37),m,True) + r_band('Body_PendulumStem',(0,-.17,1.06),(0,-.17,.80),.017,m['secondary'],5) + r_disc('Body_PendulumBob',(0,-.19,.78),.06,.028,m['secondary']) + for s,side in [(-1,'L'),(1,'R')]: + hand=(s*.53,-.11,1.52 if s<0 else 1.12) + elbow=(s*.41,.015,1.20 if s<0 else 1.02) + r_band('Arm'+side+'_Upper',(s*.22,.03,1.20),elbow,.045,m['accent'],6) + r_band('Arm'+side+'_Forearm',elbow,hand,.046,m['accent'],6) + m_joint('Arm'+side+'_Elbow',elbow,.065,m) + r_rock('Arm'+side+'_Palm',hand,(.055,.04,.07),m['accent']) + for j in range(3): + end=(hand[0]+s*.10,hand[1]-.02,hand[2]+(j-1)*.046) + r_band('Arm'+side+'_Finger'+str(j),hand,end,.012,m['accent'],4) + if s<0: + r_band('Weapon_Baton',hand,(hand[0]+.20,hand[1],hand[2]+.33),.012,m['secondary'],4) + + +def build_nietenkonvent(spec,m): + {'tank':m_boiler,'melee':m_shear,'ranged':m_ranged,'artillery':m_resonator,'support':m_conductor}[spec['role']](spec['upgraded'],m) + +from math import sin,cos,pi + + +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) + +from math import sin,cos,pi + + +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) + +from math import cos, pi, sin + + + +def _prism(name, outline, front_y, back_y, material): + """Extrude an X/Z outline along Y, useful for readable masks and wedges.""" + area = sum(outline[i][0] * outline[(i + 1) % len(outline)][1] + - outline[(i + 1) % len(outline)][0] * outline[i][1] + for i in range(len(outline))) + if area < 0: + outline = list(reversed(outline)) + count = len(outline) + vertices = [(x, front_y, z) for x, z in outline] + vertices += [(x, back_y, z) for x, z in outline] + faces = [tuple(range(count)), tuple(range(2 * count - 1, count - 1, -1))] + for i in range(count): + following = (i + 1) % count + faces.append((i, i + count, following + count, following)) + return mesh_object(name, vertices, faces, material) + + +def _figure(spec, nominal_height): + """Scaled primitive wrappers keep species proportions stable at any height.""" + scale = float(spec.get("height", nominal_height)) / nominal_height + + def point(value): + return tuple(component * scale for component in value) + + class Figure: + def box(self, name, loc, size, material, rotation=None): + return box(name, point(loc), point(size), material, rotation=rotation) + + def ellipsoid(self, name, loc, size, material, subdivisions=1): + return ellipsoid(name, point(loc), point(size), material, subdivisions=subdivisions) + + def cylinder(self, name, loc, radius, depth, material, vertices=8, rotation=None): + return cylinder(name, point(loc), radius * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def cone(self, name, loc, radius1, radius2, depth, material, vertices=8, rotation=None): + return cone(name, point(loc), radius1 * scale, radius2 * scale, depth * scale, + material, vertices=vertices, rotation=rotation) + + def beam(self, name, start, end, radius, material, vertices=6): + return beam(name, point(start), point(end), radius * scale, + material, vertices=vertices) + + def ring(self, name, loc, major_radius, minor_radius, material, + rotation=None, segments=10): + return ring(name, point(loc), major_radius * scale, minor_radius * scale, + material, rotation=rotation, segments=segments) + + def prism(self, name, outline, front_y, back_y, material): + return _prism(name, [(x * scale, z * scale) for x, z in outline], + front_y * scale, back_y * scale, material) + + return Figure() + + +def _boots(f, material, x=0.22, width=0.26, height=0.18, depth=0.42): + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side + "_Boot", (sign * x, -0.075, height / 2), + (width, depth, height), material) + + +def _eyes(f, material, z, y, separation=0.10): + for side, sign in (("L", -1), ("R", 1)): + f.box("Head_Eye" + side, (sign * separation, y, z), + (0.065, 0.025, 0.034), material) + + +def build_lane(spec, mat): + """12 m traversable width, 4 m repeat length, deck at Z=0. + + Side decoration remains strictly outside X=[-6,+6], and nothing extends + past Y=[-2,+2], so consecutive copies meet without a transverse obstacle. + """ + box("Body_LaneFoundation", (0, 0, -0.195), (12, 4, 0.31), mat["primary"]) + for column in range(6): + box("Body_LaneSlab_%02d" % column, (-5 + column * 2, 0, -0.02), + (2, 4, 0.04), mat["primary"]) + for side, sign in (("L", -1), ("R", 1)): + box("Body_" + side + "RetainingLip", (sign * 6.15, 0, -0.10), + (0.30, 4, 0.50), mat["secondary"]) + for index, y in enumerate((-1.42, 0, 1.42)): + ellipsoid("Body_" + side + "Basalt_%02d" % index, + (sign * 6.46, y, -0.05), + (0.26, 0.42, 0.26 if index != 1 else 0.30), mat["secondary"]) + for index, y in enumerate((-1.15, 1.15)): + box("Body_" + side + "BrassMarker_%02d" % index, + (sign * 6.15, y, 0.165), (0.19, 0.20, 0.03), mat["accent"]) + ellipsoid("Body_" + side + "Moss", (sign * 6.39, 0.65, 0.02), + (0.17, 0.34, 0.13), mat["light"]) + empty("Anchor_Deck", (0, 0, 0)) + empty("Anchor_JoinNorth", (0, 2, 0)) + empty("Anchor_JoinSouth", (0, -2, 0)) + + +def build_core(spec, mat): + """A grounded crystal cradle with a physical team circle or triangle.""" + triangular = int(spec.get("team", 0)) == 1 + sides = 3 if triangular else 12 + cylinder("Body_CorePlinth", (0, 0, 0.13), 1.26, 0.26, + mat["primary"], vertices=sides) + cylinder("Body_BrassPlinthRim", (0, 0, 0.285), 1.18, 0.05, + mat["secondary"], vertices=sides) + cylinder("Body_CradleStep", (0, 0, 0.37), 0.85, 0.12, + mat["primary"], vertices=8) + if triangular: + points = [(1.06 * sin(i * 2 * pi / 3), -1.06 * cos(i * 2 * pi / 3), 0.34) + for i in range(3)] + for i in range(3): + beam("Team_Triangle_%d" % i, points[i], points[(i + 1) % 3], + 0.045, mat["accent"], vertices=6) + else: + ring("Team_Circle", (0, 0, 0.345), 1.025, 0.045, mat["accent"], segments=20) + # Multiple low-poly rings create a recognizable mineral, not a sphere. + vertices = [(0, 0, 0.51)] + for radius, z in ((0.37, 0.70), (0.58, 1.16), (0.36, 1.72)): + vertices.extend((radius * cos(i * pi / 3), radius * sin(i * pi / 3), z) + for i in range(6)) + vertices.append((0, 0, 2.20)) + faces = [(0, 1 + (i + 1) % 6, 1 + i) for i in range(6)] + for row in range(2): + start = 1 + 6 * row + for i in range(6): + following = (i + 1) % 6 + faces.append((start + i, start + following, + start + 6 + following, start + 6 + i)) + faces.extend((13 + i, 13 + (i + 1) % 6, 19) for i in range(6)) + mesh_object("Body_CoreCrystal", vertices, faces, mat["accent"]) + for index in range(4): + angle = pi / 4 + index * pi / 2 + x, y = sin(angle), cos(angle) + beam("Arm_Cradle_%d" % index, (x * 0.72, y * 0.72, 0.42), + (x * 0.47, y * 0.47, 0.88), 0.075, mat["secondary"]) + ellipsoid("Arm_CradleClasp_%d" % index, + (x * 0.48, y * 0.48, 0.85), (0.12, 0.12, 0.09), mat["light"]) + empty("Anchor_CoreEffect", (0, 0, 1.25)) + + +def build_worker(spec, mat): + """Small clay Funkenleser with a fork and a framed energy container.""" + f = _figure(spec, 1.1) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.14, depth=0.31) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.16, 0, 0.14), + (sign * 0.15, 0, 0.36), 0.10, mat["primary"]) + f.ellipsoid("Body_Clay", (0, 0, 0.49), (0.30, 0.21, 0.30), mat["primary"]) + f.prism("Body_Apron", [(-0.20, 0.68), (-0.24, 0.30), (0.24, 0.30), (0.20, 0.68)], + -0.23, -0.19, mat["secondary"]) + f.box("Body_Buckle", (0, -0.248, 0.56), (0.10, 0.035, 0.07), mat["accent"]) + f.ellipsoid("Head_Hood", (0, 0.005, 0.88), (0.26, 0.235, 0.22), mat["secondary"]) + f.ellipsoid("Head_ClayFace", (0, -0.175, 0.88), (0.195, 0.10, 0.17), mat["primary"]) + _eyes(f, mat["secondary"], 0.905, -0.274, separation=0.075) + f.beam("ArmL", (-0.23, 0, 0.64), (-0.40, -0.19, 0.52), 0.085, mat["primary"]) + f.beam("ArmR", (0.23, 0, 0.64), (0.39, -0.23, 0.54), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.40, -0.19, 0.52), (0.105, 0.09, 0.09), mat["primary"]) + f.ellipsoid("ArmR_Hand", (0.39, -0.23, 0.54), (0.105, 0.09, 0.09), mat["primary"]) + f.beam("Weapon_SparkForkHandle", (-0.43, -0.20, 0.13), (-0.43, -0.20, 0.78), + 0.032, mat["accent"]) + for sign in (-1, 1): + f.beam("Weapon_SparkForkProng_%d" % sign, (-0.43, -0.20, 0.78), + (-0.43 + sign * 0.10, -0.20, 0.99), 0.026, mat["accent"]) + f.cylinder("Weapon_ContainerBase", (0.44, -0.24, 0.32), 0.11, 0.045, mat["accent"]) + f.cylinder("Weapon_ContainerLid", (0.44, -0.24, 0.61), 0.11, 0.045, mat["accent"]) + # An open brass cage gives glass-like legibility without alpha sorting. + for index in range(4): + angle = index * pi / 2 + f.beam("Weapon_ContainerRib_%d" % index, + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.33), + (0.44 + cos(angle) * 0.085, -0.24 + sin(angle) * 0.085, 0.60), + 0.016, mat["accent"], vertices=4) + f.ellipsoid("Weapon_CapturedSpark", (0.44, -0.24, 0.47), + (0.058, 0.058, 0.105), mat["light"]) + + +def _scout(spec, mat): + f = _figure(spec, 1.70) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.18) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side, (sign * 0.18, 0, 0.17), + (sign * 0.15, 0, 0.78), 0.087, mat["primary"]) + f.box("Leg" + side + "_ShinPlate", (sign * 0.18, -0.095, 0.35), + (0.13, 0.05, 0.24), mat["secondary"]) + f.cone("Body_Armor", (0, 0, 0.97), 0.22, 0.28, 0.49, mat["primary"], vertices=6) + f.box("Body_Belt", (0, 0, 0.77), (0.44, 0.30, 0.10), mat["secondary"]) + f.ellipsoid("Head_Hood", (0, 0.015, 1.42), (0.23, 0.21, 0.25), mat["primary"]) + f.cone("Head_HoodPoint", (0, 0.055, 1.60), 0.145, 0, 0.20, mat["primary"], vertices=5) + f.prism("Head_Mask", [(-0.15, 1.54), (-0.13, 1.32), (0, 1.26), (0.13, 1.32), (0.15, 1.54)], + -0.21, -0.165, mat["light"]) + _eyes(f, mat["primary"], 1.46, -0.225, separation=0.075) + f.beam("ArmL_Upper", (-0.24, 0, 1.12), (-0.34, -0.17, 0.96), 0.078, mat["primary"]) + f.beam("ArmL_Fore", (-0.34, -0.17, 0.96), (-0.06, -0.37, 1.02), 0.071, mat["primary"]) + f.beam("ArmR_Upper", (0.24, 0, 1.12), (0.35, -0.15, 0.97), 0.078, mat["primary"]) + f.beam("ArmR_Fore", (0.35, -0.15, 0.97), (0.25, -0.43, 1.07), 0.071, mat["primary"]) + f.box("Weapon_DartLauncherStock", (0.19, -0.34, 1.07), (0.19, 0.44, 0.15), mat["secondary"]) + f.cylinder("Weapon_DartLauncherBarrel", (0.19, -0.66, 1.09), + 0.065, 0.34, mat["light"], rotation=(pi / 2, 0, 0)) + f.cylinder("Weapon_DartLauncherBore", (0.19, -0.836, 1.09), + 0.04, 0.008, mat["primary"], rotation=(pi / 2, 0, 0)) + f.box("Body_DartQuiver", (-0.14, 0.23, 1.02), (0.23, 0.17, 0.45), mat["secondary"], + rotation=(0, -0.16, 0)) + for index in range(3): + x = -0.23 + index * 0.085 + f.beam("Weapon_SpareDart_%d" % index, (x, 0.24, 1.10), (x - 0.06, 0.24, 1.47), + 0.024, mat["light"], vertices=4) + + +def _ram(spec, mat): + f = _figure(spec, 1.48) + _boots(f, mat["primary"], x=0.27, width=0.35, height=0.20, depth=0.45) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.27, 0, 0.35), (0.25, 0.30, 0.35), mat["primary"]) + f.ellipsoid("Arm" + side + "_Pauldron", (sign * 0.43, 0, 1.05), + (0.27, 0.25, 0.25), mat["secondary"]) + f.box("Body_RustArmor", (0, 0, 0.83), (0.74, 0.48, 0.67), mat["secondary"]) + f.box("Body_UpperLamella", (0, -0.256, 1.01), (0.71, 0.06, 0.18), mat["primary"]) + f.box("Body_LowerLamella", (0, -0.261, 0.80), (0.71, 0.06, 0.16), mat["primary"]) + f.ellipsoid("Head_Helmet", (0, 0, 1.29), (0.27, 0.23, 0.19), mat["primary"]) + f.box("Head_BrowGuard", (0, -0.23, 1.35), (0.45, 0.085, 0.10), mat["light"]) + _eyes(f, mat["accent"], 1.275, -0.235) + f.beam("ArmL", (-0.43, 0, 1.03), (-0.43, -0.40, 0.81), 0.14, mat["primary"]) + f.beam("ArmR", (0.43, 0, 1.03), (0.61, -0.18, 0.72), 0.14, mat["primary"]) + f.box("ArmR_HammerFist", (0.61, -0.19, 0.66), (0.30, 0.28, 0.29), mat["secondary"]) + outline = [(-0.63, 1.09), (-0.68, 0.34), (-0.48, 0.21), (0.45, 0.21), + (0.65, 0.34), (0.60, 1.09)] + f.prism("Weapon_RamShield", outline, -0.54, -0.39, mat["secondary"]) + f.box("Weapon_ShieldTopRim", (-0.015, -0.575, 1.05), (1.18, 0.07, 0.095), mat["light"]) + f.prism("Weapon_CentralWedge", [(-0.13, 0.94), (-0.18, 0.37), (0, 0.28), (0.18, 0.37), (0.13, 0.94)], + -0.74, -0.53, mat["primary"]) + + +def _singer(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.18, width=0.23, height=0.12, depth=0.32) + f.cone("Body_BellRobe", (0, 0, 0.63), 0.43, 0.20, 1.10, mat["primary"], vertices=8) + for index, x in enumerate((-0.22, 0, 0.22)): + f.prism("Body_RobeFold_%d" % index, + [(x - 0.055, 0.15), (x + 0.055, 0.15), (x * 0.45, 1.09)], + -0.32, -0.24, mat["accent"]) + f.ellipsoid("Body_Mantle", (0, 0, 1.24), (0.37, 0.27, 0.21), mat["accent"]) + f.ellipsoid("Head_DeepHood", (0, 0, 1.57), (0.26, 0.25, 0.25), mat["primary"]) + f.prism("Head_SingerMask", [(-0.13, 1.68), (-0.12, 1.47), (0, 1.41), (0.12, 1.47), (0.13, 1.68)], + -0.246, -0.21, mat["light"]) + _eyes(f, mat["primary"], 1.60, -0.257, separation=0.065) + f.beam("ArmL", (-0.29, 0, 1.27), (-0.34, -0.37, 1.05), 0.085, mat["primary"]) + f.beam("ArmR", (0.29, 0, 1.27), (0.36, -0.43, 1.10), 0.085, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.34, -0.37, 1.05), (0.095, 0.075, 0.075), mat["light"]) + f.ellipsoid("ArmR_Hand", (0.36, -0.43, 1.10), (0.095, 0.075, 0.075), mat["light"]) + f.beam("Weapon_HornPipe", (-0.30, -0.37, 1.08), (0.36, -0.43, 1.13), 0.075, mat["secondary"]) + # A true open bell: two rings connected by a tapered shell, no filled mouth. + vertices = [] + for y, radius in ((-0.43, 0.075), (-0.84, 0.28), (-0.81, 0.235), (-0.47, 0.042)): + for index in range(10): + angle = index * pi / 5 + vertices.append((0.36 + cos(angle) * radius, y, 1.13 + sin(angle) * radius)) + faces = [] + for row in range(3): + for i in range(10): + j = (i + 1) % 10 + faces.append((row * 10 + i, row * 10 + j, (row + 1) * 10 + j, (row + 1) * 10 + i)) + scale = float(spec.get("height", 1.82)) / 1.82 + mesh_object("Weapon_ResonanceHorn", [tuple(v * scale for v in point) for point in vertices], + faces, mat["secondary"]) + f.ring("Weapon_HornRim", (0.36, -0.84, 1.13), 0.258, 0.023, mat["light"], + rotation=(pi / 2, 0, 0)) + + +def _breaker(spec, mat): + f = _figure(spec, 1.82) + _boots(f, mat["primary"], x=0.28, width=0.36, height=0.22, depth=0.49) + for side, sign in (("L", -1), ("R", 1)): + f.box("Leg" + side, (sign * 0.26, 0, 0.47), (0.28, 0.31, 0.54), mat["primary"]) + f.box("Leg" + side + "_Knee", (sign * 0.27, -0.19, 0.51), + (0.27, 0.13, 0.24), mat["secondary"]) + f.box("Arm" + side + "_Pauldron", (sign * 0.48, 0, 1.29), + (0.42, 0.52, 0.34), mat["primary"], rotation=(0, sign * 0.14, 0)) + f.cone("Body_SteelTorso", (0, 0, 1.01), 0.35, 0.47, 0.70, mat["primary"], vertices=6) + f.prism("Body_RustChestInset", [(-0.28, 1.29), (0, 0.95), (0.28, 1.29)], + -0.397, -0.35, mat["secondary"]) + f.box("Head_Helmet", (0, 0, 1.61), (0.43, 0.40, 0.42), mat["primary"]) + f.prism("Head_Faceplate", [(-0.17, 1.76), (-0.17, 1.50), (0, 1.44), (0.17, 1.50), (0.17, 1.76)], + -0.23, -0.19, mat["light"]) + f.box("Head_Visor", (0, -0.246, 1.66), (0.25, 0.026, 0.045), mat["primary"]) + f.beam("ArmL", (-0.47, 0, 1.25), (-0.31, -0.50, 0.92), 0.12, mat["primary"]) + f.beam("ArmR", (0.47, 0, 1.25), (0.30, -0.50, 1.20), 0.12, mat["primary"]) + f.ellipsoid("ArmL_Hand", (-0.31, -0.50, 0.92), (0.145, 0.12, 0.12), mat["secondary"]) + f.ellipsoid("ArmR_Hand", (0.30, -0.50, 1.20), (0.145, 0.12, 0.12), mat["secondary"]) + f.beam("Weapon_HammerShaft", (-0.65, -0.51, 0.77), (0.66, -0.51, 1.36), + 0.055, mat["secondary"]) + f.prism("Weapon_KeilhammerHead", [(0.40, 1.26), (0.43, 1.58), (0.82, 1.80), + (1.02, 1.61), (0.90, 1.18)], + -0.79, -0.24, mat["primary"]) + # Offset along the sloped edge normal; coplanar cap faces would flicker. + f.prism("Weapon_ChiselEdge", [(0.832, 1.814), (1.032, 1.624), (0.992, 1.354), (0.932, 1.644)], + -0.80, -0.23, mat["light"]) + + +def _rift(spec, mat): + f = _figure(spec, 2.08) + _boots(f, mat["primary"], x=0.22, width=0.21, height=0.12, depth=0.35) + for side, sign in (("L", -1), ("R", 1)): + f.beam("Leg" + side + "_Shin", (sign * 0.22, 0, 0.12), + (sign * 0.30, 0.12, 0.45), 0.069, mat["primary"]) + f.beam("Leg" + side + "_Thigh", (sign * 0.30, 0.12, 0.45), + (sign * 0.17, 0, 0.81), 0.083, mat["primary"]) + f.ellipsoid("Body_Pelvis", (0, 0, 0.83), (0.25, 0.16, 0.16), mat["primary"]) + # Separate ribs bound real negative space; there is deliberately no chest fill. + for side, sign in (("L", -1), ("R", 1)): + f.beam("Body_" + side + "LowerRib", (sign * 0.15, 0, 0.89), + (sign * 0.31, 0, 1.18), 0.095, mat["primary"]) + f.beam("Body_" + side + "UpperRib", (sign * 0.31, 0, 1.18), + (sign * 0.21, 0, 1.52), 0.10, mat["primary"]) + f.beam("Body_" + side + "RiftSeam", (sign * 0.17, -0.080, 0.95), + (sign * 0.245, -0.080, 1.18), 0.019, mat["accent"], vertices=4) + f.beam("Body_" + side + "RiftUpperSeam", (sign * 0.245, -0.080, 1.18), + (sign * 0.16, -0.080, 1.46), 0.019, mat["accent"], vertices=4) + f.beam("Body_Collar", (-0.21, 0, 1.52), (0.21, 0, 1.52), 0.095, mat["primary"]) + f.ellipsoid("Head_HollowShell", (0, 0, 1.73), (0.20, 0.155, 0.23), mat["primary"]) + f.box("Head_RiftMouth", (0, -0.153, 1.69), (0.17, 0.025, 0.043), mat["accent"]) + for index, (x, z) in enumerate(((-0.19, 1.90), (-0.10, 2.02), (0.10, 2.02), (0.19, 1.90))): + f.beam("Head_BrokenCrown_%d" % index, (x, 0, z - 0.13), (x * 1.18, 0, z + 0.06), + 0.038, mat["light"], vertices=5) + f.beam("ArmL_Upper", (-0.30, 0, 1.47), (-0.48, 0.02, 1.13), 0.068, mat["primary"]) + f.beam("ArmL_Fore", (-0.48, 0.02, 1.13), (-0.46, -0.18, 0.77), 0.056, mat["primary"]) + for index in range(3): + f.beam("ArmL_Claw_%d" % index, (-0.50 + index * 0.043, -0.18, 0.79), + (-0.51 + index * 0.049, -0.25, 0.64), 0.020, mat["light"], vertices=4) + f.beam("ArmR_Upper", (0.30, 0, 1.47), (0.49, 0, 1.10), 0.068, mat["primary"]) + f.beam("ArmR_Fore", (0.49, 0, 1.10), (0.37, -0.33, 1.23), 0.056, mat["primary"]) + f.ellipsoid("ArmR_CradlingHand", (0.37, -0.33, 1.23), (0.12, 0.09, 0.052), mat["primary"]) + f.ellipsoid("Weapon_DrainOrb", (0.37, -0.34, 1.40), (0.13, 0.13, 0.13), mat["accent"]) + f.ring("Weapon_DrainOrbit", (0.37, -0.34, 1.40), 0.175, 0.015, + mat["light"], rotation=(0.35, 0.20, 0), segments=10) + + +def build_mercenary(spec, mat): + """Dispatch five neutral mercenaries, retaining recognizable role silhouettes.""" + builders = {"s01": _scout, "s02": _ram, "s03": _singer, + "s04": _breaker, "s05": _rift} + identifier = str(spec["id"]) + if identifier not in builders: + raise ValueError("Unknown Saumwacht mercenary: " + identifier) + builders[identifier](spec, mat) + + +def _builder(role): + return globals()["build_" + role] + + +import hashlib +import json +from pathlib import Path +import struct + +import bpy +from mathutils import Vector + + + + + +def bounds(objects): + bpy.context.view_layer.update() + points = [obj.matrix_world @ Vector(corner) for obj in objects if obj.type == 'MESH' + for corner in obj.bound_box] + if not points: + raise ValueError('No mesh geometry was generated') + return (Vector([min(point[i] for point in points) for i in range(3)]), + Vector([max(point[i] for point in points) for i in range(3)])) + + +def _bake_parts(objects): + """Keep each part's origin, but bake its local rotation/scale into the mesh.""" + for obj in objects: + if obj.type != 'MESH': + continue + obj.data.transform(obj.matrix_basis.to_3x3().to_4x4()) + obj.rotation_euler = (0, 0, 0) + obj.scale = (1, 1, 1) + obj.data.update() + + +def _fit_to_cell(objects, spec): + low, high = bounds(objects) + dims = high - low + if spec['role'] == 'lane': + # Tile top stays at Z=0; thickness and decorative lip may cross that plane. + return 1.0 + factor = min(spec['height'] / dims.z, spec['footprint'] / max(dims.x, dims.y)) + center = Vector(((low.x + high.x) / 2, (low.y + high.y) / 2, low.z)) + for obj in objects: + obj.location = (obj.location - center) * factor + obj.scale *= factor + _bake_parts(objects) + return factor + + +def _canonical_glb_names(path): + """Make GLB part names independent of other objects open in Blender. + + Blender may add .001 to datablock names in a populated session. Exported + custom properties retain logical part names; this changes JSON names only, + preserving all mesh buffers and material data produced by bpy's exporter. + """ + raw = path.read_bytes() + magic, version, length = struct.unpack_from('<4sII', raw) + if (magic, version, length) != (b'glTF', 2, len(raw)): + raise ValueError('Invalid GLB container') + chunks, offset = [], 12 + while offset < len(raw): + size, kind = struct.unpack_from(' cap: + raise ValueError(f'{asset_id}: {triangles} triangles exceeds {cap}') + root = empty('Model_' + asset_id) + root['asset_id'] = asset_id + root['faction'] = spec['faction'] + root['role'] = spec['role'] + root['forward_axis'] = '+Z in glTF/Godot' + root['phase'] = 7 if spec.get('detail_level') == 'high' else 4 + for obj in objects: + obj.parent = root + marker = empty('Forward', (0, -0.75, 0)) + marker.parent = root + bpy.ops.object.select_all(action='DESELECT') + for obj in scene.objects: + obj.select_set(True) + bpy.context.view_layer.objects.active = root + glb_path = export_dir / spec['file'] + bpy.ops.export_scene.gltf(filepath=str(glb_path), export_format='GLB', + use_selection=True, use_active_scene=True, export_yup=True, + export_apply=True, export_materials='EXPORT', + export_extras=True, export_cameras=False, + export_lights=False, export_animations=False) + _canonical_glb_names(glb_path) + blend_path = blend_dir / (asset_id + '.blend') + # Offline sculpt detail is saved only after the runtime export. + add_offline_sculpt_modifiers(objects) + add_offline_materials(objects, PROJECT) + # Write this scene and its dependencies, never the user's other scenes. + bpy.data.libraries.write(str(blend_path), {scene}, path_remap='RELATIVE_ALL', fake_user=True, compress=True) + resource_path = 'res://' + glb_path.relative_to(PROJECT).as_posix() if glb_path.is_relative_to(PROJECT) else None + record = {**spec, 'resource_path': resource_path, + 'export_path': str(glb_path), 'blend_path': str(blend_path), + 'triangles': triangles, 'offline_sculpt_parts': sum(bool(o.get('sculpt_surface')) for o in objects), + 'offline_render_triangles': sum(len(o.data.loop_triangles)*(16 if o.get('sculpt_surface') else 1) for o in objects if o.type == 'MESH'), 'mesh_parts': sum(obj.type == 'MESH' for obj in objects), + 'parts': [obj.get('part_name', obj.name) for obj in objects], + 'bounds_blender': {'min': list(low), 'max': list(high)}, + 'bounds_godot': {'min': [low.x, low.z, -high.y], 'max': [high.x, high.z, -low.y]}, + 'scale_applied': factor, 'blender_version': bpy.app.version_string, + 'sha256': hashlib.sha256(glb_path.read_bytes()).hexdigest(), + 'source': 'Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.', + 'status': 'exported'} + (record_dir / (asset_id + '.json')).write_text(json.dumps(record, ensure_ascii=False, indent=2) + '\n') + completed = True + print(f'EXPORTED {asset_id}: {triangles} triangles, {record["mesh_parts"]} parts -> {glb_path}') + return record + finally: + if not keep_scene or not completed: + bpy.context.window.scene = previous_scene + owned = list(scene.objects) + meshes = [obj.data for obj in owned if obj.type == 'MESH'] + materials = {mat for mesh in meshes for mat in mesh.materials if mat is not None} + bpy.data.scenes.remove(scene) + for obj in owned: + if obj.users == 0: + bpy.data.objects.remove(obj) + for mesh in meshes: + if mesh.users == 0: + bpy.data.meshes.remove(mesh) + for mat in materials: + if mat.users == 0: + bpy.data.materials.remove(mat) + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() diff --git a/assets-source/phase5/revisions/before-integration.tar.gz b/assets-source/phase5/revisions/before-integration.tar.gz new file mode 100644 index 0000000..a515ab1 Binary files /dev/null and b/assets-source/phase5/revisions/before-integration.tar.gz differ diff --git a/assets-source/phase6/export-templates/linux_release.x86_64 b/assets-source/phase6/export-templates/linux_release.x86_64 new file mode 100644 index 0000000..b7a063b Binary files /dev/null and b/assets-source/phase6/export-templates/linux_release.x86_64 differ diff --git a/assets-source/phase6/export-templates/version.txt b/assets-source/phase6/export-templates/version.txt new file mode 100644 index 0000000..207d581 --- /dev/null +++ b/assets-source/phase6/export-templates/version.txt @@ -0,0 +1 @@ +4.7.2.stable diff --git a/assets-source/phase6/export-templates/windows_release_x86_64.exe b/assets-source/phase6/export-templates/windows_release_x86_64.exe new file mode 100644 index 0000000..aff428d Binary files /dev/null and b/assets-source/phase6/export-templates/windows_release_x86_64.exe differ diff --git a/assets-source/phase6/licenses/GODOT-COPYRIGHT.txt b/assets-source/phase6/licenses/GODOT-COPYRIGHT.txt new file mode 100644 index 0000000..758917a --- /dev/null +++ b/assets-source/phase6/licenses/GODOT-COPYRIGHT.txt @@ -0,0 +1,2379 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Comment: + Exhaustive licensing information for files in the Godot Engine repository + ========================================================================= + . + This file aims at documenting the copyright and license for every source + file in the Godot Engine repository, and especially outline the files + whose license differs from the MIT/Expat license used by Godot Engine. + . + It is written as a machine-readable format following the debian/copyright + specification. Globbing patterns (e.g. "Files: *") mean that they affect + all corresponding files (also recursively in subfolders), apart from those + with a more explicit copyright statement. + . + Licenses are given with their debian/copyright short name (or SPDX identifier + if no standard short name exists) and are all included in plain text at the + end of this file (in alphabetical order). + . + Disclaimer for thirdparty libraries: + ------------------------------------ + . + Licensing details for thirdparty libraries in the 'thirdparty/' directory + are given in summarized form, i.e. with only the "main" license described + in the library's license statement. Different licenses of single files or + code snippets in thirdparty libraries are not documented here. + For example: + Files: thirdparty/zlib/* + Copyright: 1995-2017, Jean-loup Gailly and Mark Adler + License: Zlib + The exact copyright for each file in that library *may* differ, and some + files or code snippets might be distributed under other compatible licenses + (e.g. a public domain dedication), but as far as Godot Engine is concerned + the library is considered as a whole under the Zlib license. + . + Note: When linking dynamically against thirdparty libraries instead of + building them into the Godot binary, you may remove the corresponding + license details from this file. +Upstream-Name: Godot Engine +Upstream-Contact: Rémi Verschelde +Source: https://github.com/godotengine/godot + +Files: * +Comment: Godot Engine +Copyright: 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat + +Files: core/math/convex_hull.cpp + core/math/convex_hull.h +Comment: Bullet Continuous Collision Detection and Physics Library +Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat and Zlib + +Files: misc/dist/linux/org.godotengine.Godot.appdata.xml +Comment: Linux AppStream Metadata File +Copyright: 2017-2022, Rémi Verschelde +License: CC0-1.0 + +Files: misc/logo/* +Comment: Godot Engine logo +Copyright: 2017, Andrea Calabró +License: CC-BY-4.0 + +Files: modules/betsy/alpha_stitch.glsl + modules/betsy/bc1.glsl + modules/betsy/bc4.glsl + modules/betsy/bc6h.glsl +Comment: Betsy +Copyright: 2020-2022, Matias N. Goldberg +License: Expat + +Files: modules/godot_physics_2d/godot_joints_2d.cpp +Comment: Chipmunk2D Joint Constraints +Copyright: 2007, Scott Lembcke +License: Expat + +Files: modules/godot_physics_3d/gjk_epa.cpp + modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp + modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h + modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp + modules/godot_physics_3d/joints/godot_hinge_joint_3d.h + modules/godot_physics_3d/joints/godot_jacobian_entry_3d.h + modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp + modules/godot_physics_3d/joints/godot_pin_joint_3d.h + modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp + modules/godot_physics_3d/joints/godot_slider_joint_3d.h + modules/godot_physics_3d/godot_soft_body_3d.cpp + modules/godot_physics_3d/godot_soft_body_3d.h + modules/godot_physics_3d/godot_shape_3d.cpp + modules/godot_physics_3d/godot_shape_3d.h +Comment: Bullet Continuous Collision Detection and Physics Library +Copyright: 2003-2008, Erwin Coumans + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat and Zlib + +Files: modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp +Comment: Open Dynamics Engine +Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh +License: BSD-3-clause + +Files: modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp + modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h +Comment: Bullet Continuous Collision Detection and Physics Library +Copyright: 2007, Starbreeze Studios + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat and Zlib + +Files: modules/jolt_physics/spaces/jolt_temp_allocator.cpp +Comment: Jolt Physics +Copyright: 2021, Jorrit Rouwe + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat + +Files: modules/lightmapper_rd/lm_compute.glsl +Comment: Joint Non-Local Means (JNLM) denoiser +Copyright: 2020, Manuel Prandini + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat + +Files: platform/android/java/editor/src/main/java/com/android/* + platform/android/java/lib/src/main/aidl/com/android/* + platform/android/java/lib/src/main/res/layout/status_bar_ongoing_event_progress_bar.xml + platform/android/java/lib/src/main/java/com/google/android/* +Comment: The Android Open Source Project +Copyright: 2008-2016, The Android Open Source Project + 2002, Google, Inc. +License: Apache-2.0 + +Files: platform/android/java/lib/src/main/java/org/godotengine/godot/utils/ProcessPhoenix.java +Comment: ProcessPhoenix +Copyright: 2015, Jake Wharton +License: Apache-2.0 + +Files: scene/animation/easing_equations.h +Comment: Robert Penner's Easing Functions +Copyright: 2001, Robert Penner + 2014-present, Godot Engine contributors + 2007-2014, Juan Linietsky, Ariel Manzur +License: Expat + +Files: servers/audio/effects/audio_effect_pitch_shift.cpp +Copyright: 2014-present Godot Engine contributors + 2007-2014 Juan Linietsky, Ariel Manzur + 1999-2015 Stephan M. Bernsee +License: Expat and WOL + +Files: servers/rendering/renderer_rd/shaders/effects/tonemap.glsl +Comment: NVidia's FXAA 3.11, simplified by Simon Rodriguez +Copyright: 2014-2015, NVIDIA CORPORATION + 2017 Simon Rodriguez +License: BSD-3-clause and Expat + +Files: servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl + servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl + servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl + servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl + servers/rendering/renderer_rd/shaders/effects/ssao.glsl + servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl + servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl + servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl + servers/rendering/renderer_rd/shaders/effects/ssil.glsl +Comment: Intel ASSAO and related files +Copyright: 2016, Intel Corporation +License: Expat + +Files: servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl +Comment: Temporal Anti-Aliasing resolve implementation +Copyright: 2016, Panos Karabelas +License: Expat + +Files: servers/rendering/renderer_rd/shaders/effects/smaa_blending.glsl + servers/rendering/renderer_rd/shaders/effects/smaa_weight_calculation.glsl + servers/rendering/renderer_rd/shaders/effects/smaa_edge_detection.glsl + thirdparty/smaa/* +Comment: Subpixel Morphological Antialiasing +Copyright: 2013, Jorge Jimenez + 2013, Jose I. Echevarria + 2013, Belen Masia + 2013, Fernando Navarro + 2013, Diego Gutierrez +License: Expat + +Files: thirdparty/accesskit/* +Comment: AccessKit +Copyright: 2023, The AccessKit Authors. +License: Expat + +Files: thirdparty/amd-fsr/* +Comment: AMD FidelityFX Super Resolution +Copyright: 2021, Advanced Micro Devices, Inc. +License: Expat + +Files: thirdparty/amd-fsr2/* +Comment: AMD FidelityFX Super Resolution 2 +Copyright: 2022-2023, Advanced Micro Devices, Inc. +License: Expat + +Files: thirdparty/angle/* +Comment: ANGLE +Copyright: 2018, The ANGLE Project Authors. +License: BSD-3-clause + +Files: thirdparty/astcenc/* +Comment: Arm ASTC Encoder +Copyright: 2011-2025, Arm Limited +License: Apache-2.0 + +Files: thirdparty/basis_universal/* +Comment: Basis Universal +Copyright: 2019-2025, Binomial LLC. +License: Apache-2.0 + +Files: thirdparty/brotli/* +Comment: Brotli +Copyright: 2009, 2010, 2013-2016 by the Brotli Authors. +License: Expat + +Files: thirdparty/certs/ca-bundle.crt +Comment: CA certificates +Copyright: Mozilla Contributors +License: MPL-2.0 + +Files: thirdparty/clipper2/* +Comment: Clipper2 +Copyright: 2010-2025, Angus Johnson +License: BSL-1.0 + +Files: thirdparty/cvtt/* +Comment: Convection Texture Tools Stand-Alone Kernels +Copyright: 2018, Eric Lasota + 2018, Microsoft Corp. +License: Expat + +Files: thirdparty/d3d12ma/* +Comment: D3D12 Memory Allocator +Copyright: 2019-2022 Advanced Micro Devices, Inc. +License: Expat + +Files: thirdparty/directx_headers/* +Comment: DirectX Headers +Copyright: Microsoft Corporation +License: Expat + +Files: thirdparty/doctest/* +Comment: doctest +Copyright: 2016-2023, Viktor Kirilov +License: Expat + +Files: thirdparty/dr_libs/* +Comment: dr_libs +Copyright: 2020, David Reid +License: Unlicense or MIT-0 + +Files: thirdparty/embree/* +Comment: Embree +Copyright: 2009-2021 Intel Corporation +License: Apache-2.0 + +Files: thirdparty/enet/* +Comment: ENet +Copyright: 2002-2024, Lee Salzman +License: Expat + +Files: thirdparty/etcpak/* +Comment: etcpak +Copyright: 2013-2022, Bartosz Taudul +License: BSD-3-clause + +Files: thirdparty/fonts/DroidSans*.woff2 +Comment: DroidSans font +Copyright: 2008, The Android Open Source Project +License: Apache-2.0 + +Files: thirdparty/fonts/Inter*.woff2 +Comment: Inter font +Copyright: 2016, The Inter Project Authors +License: OFL-1.1 + +Files: thirdparty/fonts/JetBrainsMono_Regular.woff2 +Comment: JetBrains Mono font +Copyright: 2020, JetBrains s.r.o. +License: OFL-1.1 + +Files: thirdparty/fonts/NotoSans*.woff2 +Comment: Noto Sans font +Copyright: 2012, Google Inc. +License: OFL-1.1 + +Files: thirdparty/fonts/OpenSans*.woff2 +Comment: Open Sans font +Copyright: 2020, The Open Sans Project Authors +License: OFL-1.1 + +Files: thirdparty/fonts/Vazirmatn*.woff2 +Comment: Vazirmatn font +Copyright: 2015, The Vazirmatn Project Authors. +License: OFL-1.1 + +Files: thirdparty/freetype/* +Comment: The FreeType Project +Copyright: 1996-2025, David Turner, Robert Wilhelm, and Werner Lemberg. +License: FTL + +Files: thirdparty/gamepadmotionhelpers/* +Comment: GamepadMotionHelpers +Copyright: 2020-2023, Julian "Jibb" Smart +License: Expat + +Files: thirdparty/glad/* +Comment: glad +Copyright: 2013-2022, David Herberth + 2013-2020, The Khronos Group Inc. +License: CC0-1.0 and Apache-2.0 + +Files: thirdparty/glslang/* +Comment: glslang +Copyright: 2015-2020, Google, Inc. + 2014-2020, The Khronos Group Inc + 2002, NVIDIA Corporation. +License: glslang + +Files: thirdparty/graphite/* +Comment: Graphite engine +Copyright: 2010, SIL International +License: Expat + +Files: thirdparty/grisu2/* +Comment: Grisu2 float serialization algorithm +Copyright: 2009, Florian Loitsch + 2018-2023, The simdjson authors +License: Expat and Apache-2.0 + +Files: thirdparty/harfbuzz/* +Comment: HarfBuzz text shaping library +Copyright: 2010-2022, Google, Inc. + 2015-2020, Ebrahim Byagowi + 2019,2020, Facebook, Inc. + 2012, 2015, Mozilla Foundation + 2011, Codethink Limited + 2008, 2010, Nokia Corporation and/or its subsidiary(-ies) + 2009, Keith Stribley + 2011, Martin Hosken and SIL International + 2007, Chris Wilson + 2005-2006, 2020-2023, Behdad Esfahbod + 2004, 2007-2010, 2013, 2021-2023, Red Hat, Inc. + 1998-2005, David Turner and Werner Lemberg + 2016, Igalia, S.L. + 2022, Matthias Clasen + 2018, 2021, Khaled Hosny + 2018-2020, Adobe, Inc. + 2013-2015, Alexei Podtelezhnikov +License: HarfBuzz + +Files: thirdparty/icu4c/* +Comment: International Components for Unicode +Copyright: 2016-2024, Unicode, Inc. +License: Unicode + +Files: thirdparty/jolt_physics/* +Comment: Jolt Physics +Copyright: 2021, Jorrit Rouwe +License: Expat + +Files: thirdparty/libbacktrace/* +Comment: libbacktrace +Copyright: 2012-2021, Free Software Foundation, Inc. +License: BSD-3-clause + +Files: thirdparty/libjpeg-turbo/* +Comment: libjpeg-turbo +Copyright: 2009-2025, D. R. Commander + 2015, Viktor Szathmáry. + 1991-2020, Thomas G. Lane, Guido Vollbeding +License: BSD-3-clause and IJG + +Files: thirdparty/libktx/* +Comment: KTX +Copyright: 2013-2020, Mark Callow + 2010-2020 The Khronos Group, Inc. +License: Apache-2.0 + +Files: thirdparty/libogg/* +Comment: OggVorbis +Copyright: 2002, Xiph.org Foundation +License: BSD-3-clause + +Files: thirdparty/libpng/* +Comment: libpng +Copyright: 1995-2026, The PNG Reference Library Authors. + 2018-2026, Cosmin Truta. + 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + 1996-1997, Andreas Dilger. + 1995-1996, Guy Eric Schalnat, Group 42, Inc. +License: Zlib + +Files: thirdparty/libtheora/* +Comment: OggTheora +Copyright: 2002-2009, Xiph.org Foundation +License: BSD-3-clause + +Files: thirdparty/libvorbis/* +Comment: OggVorbis +Copyright: 2002-2015, Xiph.org Foundation +License: BSD-3-clause + +Files: thirdparty/libwebp/* +Comment: WebP codec +Copyright: 2010, Google Inc. +License: BSD-3-clause + +Files: thirdparty/manifold/* +Comment: Manifold +Copyright: 2020-2025, The Manifold Authors +License: Apache-2.0 + +Files: thirdparty/mbedtls/* +Comment: Mbed TLS +Copyright: The Mbed TLS Contributors +License: Apache-2.0 + +Files: thirdparty/meshoptimizer/* +Comment: meshoptimizer +Copyright: 2016-2026, Arseny Kapoulkine +License: Expat + +Files: thirdparty/metal-cpp/* +Comment: metal-cpp +Copyright: 2024, Apple Inc. +License: Apache-2.0 + +Files: thirdparty/mingw-std-threads/* +Comment: mingw-std-threads +Copyright: 2016, Mega Limited +License: BSD-2-clause + +Files: thirdparty/miniupnpc/* +Comment: MiniUPnP Project +Copyright: 2005-2025, Thomas Bernard +License: BSD-3-clause + +Files: thirdparty/minizip/* +Comment: MiniZip +Copyright: 1998-2026, Gilles Vollant + 2007-2008, Even Rouault + 2009-2010, Mathias Svensson +License: Zlib + +Files: thirdparty/misc/bcdec.h +Comment: bcdec +Copyright: 2022, Sergii Kudlai +License: Expat + +Files: thirdparty/misc/cubemap_coeffs.h +Comment: Fast Filtering of Reflection Probes +Copyright: 2016, Activision Publishing, Inc. +License: Expat + +Files: thirdparty/misc/fastlz.c + thirdparty/misc/fastlz.h +Comment: FastLZ +Copyright: 2005-2020, Ariya Hidayat +License: Expat + +Files: thirdparty/misc/FastNoiseLite.h +Comment: FastNoise Lite +Copyright: 2023, Jordan Peck and contributors +License: Expat + +Files: thirdparty/misc/ifaddrs-android.cc + thirdparty/misc/ifaddrs-android.h +Comment: libjingle +Copyright: 2012-2013, Google Inc. +License: BSD-3-clause + +Files: thirdparty/misc/mikktspace.c + thirdparty/misc/mikktspace.h +Comment: Tangent Space Normal Maps implementation +Copyright: 2011, Morten S. Mikkelsen +License: Zlib + +Files: thirdparty/misc/nvapi_minimal.h +Comment: NVIDIA NVAPI (minimal excerpt) +Copyright: 2019-2022, NVIDIA Corporation +License: Expat + +Files: thirdparty/misc/ok_color.h + thirdparty/misc/ok_color_shader.h +Comment: OK Lab color space +Copyright: 2021, Björn Ottosson +License: Expat + +Files: thirdparty/misc/pcg.cpp + thirdparty/misc/pcg.h +Comment: Minimal PCG32 implementation +Copyright: 2014, M.E. O'Neill +License: Apache-2.0 + +Files: thirdparty/misc/polypartition.cpp + thirdparty/misc/polypartition.h +Comment: PolyPartition / Triangulator +Copyright: 2011-2021, Ivan Fratric and contributors +License: Expat + +Files: thirdparty/misc/qoa.h +Comment: Quite OK Audio Format +Copyright: 2023, Dominic Szablewski +License: Expat + +Files: thirdparty/misc/r128.c + thirdparty/misc/r128.h +Comment: r128 library +Copyright: Alan Hickman +License: Unlicense + +Files: thirdparty/misc/smaz.c + thirdparty/misc/smaz.h +Comment: SMAZ +Copyright: 2006-2009, Salvatore Sanfilippo +License: BSD-3-clause + +Files: thirdparty/misc/smolv.cpp + thirdparty/misc/smolv.h +Comment: SMOL-V +Copyright: 2016-2024, Aras Pranckevicius +License: Unlicense or Expat + +Files: thirdparty/misc/stb_rect_pack.h +Comment: stb libraries +Copyright: Sean Barrett +License: Unlicense or Expat + +Files: thirdparty/misc/yuv2rgb.h +Comment: YUV2RGB +Copyright: 2008-2011, Robin Watts +License: BSD-2-clause + +Files: thirdparty/msdfgen/* +Comment: Multi-channel signed distance field generator +Copyright: 2014-2025, Viktor Chlumsky +License: Expat + +Files: thirdparty/openxr/* +Comment: OpenXR Loader +Copyright: 2020-2025, The Khronos Group Inc. +License: Apache-2.0 + +Files: thirdparty/pcre2/* +Comment: PCRE2 +Copyright: 1997-2024, University of Cambridge + 2009-2024, Zoltan Herczeg +License: BSD-3-clause + +Files: thirdparty/recastnavigation/* +Comment: Recast +Copyright: 2009, Mikko Mononen +License: Zlib + +Files: thirdparty/rvo2/* +Comment: RVO2 +Copyright: 2016, University of North Carolina at Chapel Hill +License: Apache-2.0 + +Files: thirdparty/sdl/* +Comment: SDL +Copyright: 1997-2025, Sam Lantinga +License: Zlib + +Files: thirdparty/sdl/hidapi/* +Comment: hidapi +Copyright: 2010, Alan Ott, Signal 11 Software +License: BSD-3-clause + +Files: thirdparty/spirv-cross/* +Comment: SPIRV-Cross +Copyright: 2015-2021, Arm Limited +License: Apache-2.0 or Expat + +Files: thirdparty/spirv-headers/* +Comment: SPIRV-Headers +Copyright: 2015-2024, The Khronos Group Inc. +License: Expat + +Files: thirdparty/spirv-reflect/* +Comment: SPIRV-Reflect +Copyright: 2017-2022, Google Inc. +License: Apache-2.0 + +Files: thirdparty/swappy-frame-pacing/* +Comment: Swappy +Copyright: 2019, The Android Open Source Project +License: Apache-2.0 + +Files: thirdparty/thorvg/* +Comment: ThorVG +Copyright: 2020-2026, The ThorVG Project +License: Expat + +Files: thirdparty/tinyexr/* +Comment: TinyEXR +Copyright: 2014-2021, Syoyo Fujita + 2002, Industrial Light & Magic, a division of Lucas Digital Ltd. LLC +License: BSD-3-clause + +Files: thirdparty/ufbx/* +Comment: ufbx +Copyright: 2020, Samuli Raivio +License: Expat + +Files: thirdparty/vhacd/* +Comment: V-HACD +Copyright: 2011, Khaled Mamou + 2003-2009, Erwin Coumans +License: BSD-3-clause + +Files: thirdparty/volk/* +Comment: volk +Copyright: 2018-2025, Arseny Kapoulkine +License: Expat + +Files: thirdparty/vulkan/* +Comment: Vulkan Headers +Copyright: 2015-2025, The Khronos Group Inc. + 2015-2025, Valve Corporation + 2015-2025, LunarG, Inc. +License: Apache-2.0 + +Files: thirdparty/vulkan/vk_mem_alloc.h +Comment: Vulkan Memory Allocator +Copyright: 2017-2025, Advanced Micro Devices, Inc. +License: Expat + +Files: thirdparty/wayland/* +Comment: Wayland core protocol +Copyright: 2008-2012, Kristian Høgsberg + 2010-2012, Intel Corporation + 2011, Benjamin Franzke + 2012, Collabora, Ltd. +License: Expat + +Files: thirdparty/wayland-protocols/* +Comment: Wayland protocols +Copyright: 2008-2013, Kristian Høgsberg + 2010-2013, Intel Corporation + 2013, Rafael Antognolli + 2013, Jasper St. Pierre + 2014, Jonas Ådahl + 2014, Jason Ekstrand + 2014-2015, Collabora, Ltd. + 2015, Red Hat Inc. +License: Expat + +Files: thirdparty/wayland-protocols/mesa/wayland-drm.xml +Comment: Mesa Wayland protocols +Copyright: 2008-2011, Kristian Høgsberg + 2010-2011, Intel Corporation +License: X11 + +Files: thirdparty/wslay/* +Comment: Wslay +Copyright: 2011, 2012, 2015, Tatsuhiro Tsujikawa +License: Expat + +Files: thirdparty/xatlas/* +Comment: xatlas +Copyright: 2018-2020, Jonathan Young + 2013, Thekla, Inc + 2006, NVIDIA Corporation, Ignacio Castano +License: Expat + +Files: thirdparty/zlib/* +Comment: zlib +Copyright: 1995-2026, Jean-loup Gailly and Mark Adler +License: Zlib + +Files: thirdparty/zstd/* +Comment: Zstandard +Copyright: Meta Platforms, Inc. and affiliates. +License: BSD-3-clause + + + +License: Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + . + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + . + 1. Definitions. + . + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + . + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + . + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + . + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + . + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + . + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + . + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + . + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + . + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + . + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + . + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + . + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + . + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + . + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + . + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + . + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + . + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + . + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + . + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + . + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + . + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + . + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + . + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + . + END OF TERMS AND CONDITIONS + . + APPENDIX: How to apply the Apache License to your work. + . + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + . + Copyright [yyyy] [name of copyright owner] + . + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +License: BSD-2-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + . + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: BSD-3-clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + . + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + . + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +License: BSL-1.0 + Boost Software License - Version 1.0 - August 17th, 2003 + . + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + . + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +License: CC0-1.0 + CC0 1.0 Universal + . + Statement of Purpose + . + The laws of most jurisdictions throughout the world automatically confer + exclusive Copyright and Related Rights (defined below) upon the creator and + subsequent owner(s) (each and all, an "owner") of an original work of + authorship and/or a database (each, a "Work"). + . + Certain owners wish to permanently relinquish those rights to a Work for the + purpose of contributing to a commons of creative, cultural and scientific + works ("Commons") that the public can reliably and without fear of later + claims of infringement build upon, modify, incorporate in other works, reuse + and redistribute as freely as possible in any form whatsoever and for any + purposes, including without limitation commercial purposes. These owners may + contribute to the Commons to promote the ideal of a free culture and the + further production of creative, cultural and scientific works, or to gain + reputation or greater distribution for their Work in part through the use and + efforts of others. + . + For these and/or other purposes and motivations, and without any expectation + of additional consideration or compensation, the person associating CC0 with a + Work (the "Affirmer"), to the extent that he or she is an owner of Copyright + and Related Rights in the Work, voluntarily elects to apply CC0 to the Work + and publicly distribute the Work under its terms, with knowledge of his or her + Copyright and Related Rights in the Work and the meaning and intended legal + effect of CC0 on those rights. + . + 1. Copyright and Related Rights. A Work made available under CC0 may be + protected by copyright and related or neighboring rights ("Copyright and + Related Rights"). Copyright and Related Rights include, but are not limited + to, the following: + . + i. the right to reproduce, adapt, distribute, perform, display, communicate, + and translate a Work; + . + ii. moral rights retained by the original author(s) and/or performer(s); + . + iii. publicity and privacy rights pertaining to a person's image or likeness + depicted in a Work; + . + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + . + v. rights protecting the extraction, dissemination, use and reuse of data in + a Work; + . + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and + . + vii. other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations thereof. + . + 2. Waiver. To the greatest extent permitted by, but not in contravention of, + applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and + unconditionally waives, abandons, and surrenders all of Affirmer's Copyright + and Related Rights and associated claims and causes of action, whether now + known or unknown (including existing as well as future claims and causes of + action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time + extensions), (iii) in any current or future medium and for any number of + copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes + the Waiver for the benefit of each member of the public at large and to the + detriment of Affirmer's heirs and successors, fully intending that such Waiver + shall not be subject to revocation, rescission, cancellation, termination, or + any other legal or equitable action to disrupt the quiet enjoyment of the Work + by the public as contemplated by Affirmer's express Statement of Purpose. + . + 3. Public License Fallback. Should any part of the Waiver for any reason be + judged legally invalid or ineffective under applicable law, then the Waiver + shall be preserved to the maximum extent permitted taking into account + Affirmer's express Statement of Purpose. In addition, to the extent the Waiver + is so judged Affirmer hereby grants to each affected person a royalty-free, + non transferable, non sublicensable, non exclusive, irrevocable and + unconditional license to exercise Affirmer's Copyright and Related Rights in + the Work (i) in all territories worldwide, (ii) for the maximum duration + provided by applicable law or treaty (including future time extensions), (iii) + in any current or future medium and for any number of copies, and (iv) for any + purpose whatsoever, including without limitation commercial, advertising or + promotional purposes (the "License"). The License shall be deemed effective as + of the date CC0 was applied by Affirmer to the Work. Should any part of the + License for any reason be judged legally invalid or ineffective under + applicable law, such partial invalidity or ineffectiveness shall not + invalidate the remainder of the License, and in such case Affirmer hereby + affirms that he or she will not (i) exercise any of his or her remaining + Copyright and Related Rights in the Work or (ii) assert any associated claims + and causes of action with respect to the Work, in either case contrary to + Affirmer's express Statement of Purpose. + . + 4. Limitations and Disclaimers. + . + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + . + b. Affirmer offers the Work as-is and makes no representations or warranties + of any kind concerning the Work, express, implied, statutory or otherwise, + including without limitation warranties of title, merchantability, fitness + for a particular purpose, non infringement, or the absence of latent or + other defects, accuracy, or the present or absence of errors, whether or not + discoverable, all to the greatest extent permissible under applicable law. + . + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without limitation + any person's Copyright and Related Rights in the Work. Further, Affirmer + disclaims responsibility for obtaining any necessary consents, permissions + or other rights required for any use of the Work. + . + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to this + CC0 or use of the Work. + +License: CC-BY-4.0 + Creative Commons Attribution 4.0 International Public License + . + By exercising the Licensed Rights (defined below), You accept and agree + to be bound by the terms and conditions of this Creative Commons + Attribution 4.0 International Public License ("Public + License"). To the extent this Public License may be interpreted as a + contract, You are granted the Licensed Rights in consideration of Your + acceptance of these terms and conditions, and the Licensor grants You + such rights in consideration of benefits the Licensor receives from + making the Licensed Material available under these terms and + conditions. + . + Section 1 -- Definitions. + . + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + . + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + . + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + . + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + . + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + . + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + . + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + . + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + . + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + . + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + . + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + . + Section 2 -- Scope. + . + a. License grant. + . + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + . + a. reproduce and Share the Licensed Material, in whole or + in part; and + . + b. produce, reproduce, and Share Adapted Material. + . + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + . + 3. Term. The term of this Public License is specified in Section + 6(a). + . + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + . + 5. Downstream recipients. + . + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + . + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + . + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + . + b. Other rights. + . + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + . + 2. Patent and trademark rights are not licensed under this + Public License. + . + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + . + Section 3 -- License Conditions. + . + Your exercise of the Licensed Rights is expressly made subject to the + following conditions. + . + a. Attribution. + . + 1. If You Share the Licensed Material (including in modified + form), You must: + . + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + . + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + . + ii. a copyright notice; + . + iii. a notice that refers to this Public License; + . + iv. a notice that refers to the disclaimer of + warranties; + . + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + . + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + . + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + . + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + . + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + . + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + . + Section 4 -- Sui Generis Database Rights. + . + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + . + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + . + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + . + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + . + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the Licensed + Rights include other Copyright and Similar Rights. + . + Section 5 -- Disclaimer of Warranties and Limitation of Liability. + . + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + . + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + . + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + . + Section 6 -- Term and Termination. + . + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + . + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + . + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + . + 2. upon express reinstatement by the Licensor. + . + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + . + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + . + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + . + Section 7 -- Other Terms and Conditions. + . + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + . + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + . + Section 8 -- Interpretation. + . + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + . + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + . + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + . + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + . + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License: glslang + Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code + generation. Glslang proper requires use of a number of licenses, one that covers + preprocessing and others that covers non-preprocessing. + . + Bison was removed long ago. You can build glslang from the source grammar, + using tools of your choice, without using bison or any bison files. + . + Other parts, outside of glslang proper, include: + . + - gl_types.h, only needed for OpenGL-like reflection, and can be left out of + a parse and codegen project. See it for its license. + . + - update_glslang_sources.py, which is not part of the project proper and does + not need to be used. + . + - the SPIR-V "remapper", which is optional, but has the same license as + glslang proper + . + - Google tests and SPIR-V tools, and anything in the external subdirectory + are external and optional; see them for their respective licenses. + . + -------------------------------------------------------------------------------- + . + The core of glslang-proper, minus the preprocessor is licenced as follows: + . + -------------------------------------------------------------------------------- + 3-Clause BSD License + -------------------------------------------------------------------------------- + . + Copyright (C) 2015-2018 Google, Inc. + Copyright (C) + . + All rights reserved. + . + See: . + . + -------------------------------------------------------------------------------- + 2-Clause BSD License + -------------------------------------------------------------------------------- + . + Copyright 2020 The Khronos Group Inc + . + See: . + . + -------------------------------------------------------------------------------- + The MIT License + -------------------------------------------------------------------------------- + . + Copyright 2020 The Khronos Group Inc + . + See: . + . + -------------------------------------------------------------------------------- + APACHE LICENSE, VERSION 2.0 + -------------------------------------------------------------------------------- + . + See: . + . + -------------------------------------------------------------------------------- + GPL 3 with special bison exception + -------------------------------------------------------------------------------- + . + Bison implementation for Yacc-like parsers in C + . + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + . + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + . + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. + . + -------------------------------------------------------------------------------- + ================================================================================ + -------------------------------------------------------------------------------- + . + The preprocessor has the core licenses stated above, plus an additional licence: + . + Copyright (c) 2002, NVIDIA Corporation. + . + NVIDIA Corporation("NVIDIA") supplies this software to you in + consideration of your agreement to the following terms, and your use, + installation, modification or redistribution of this NVIDIA software + constitutes acceptance of these terms. If you do not agree with these + terms, please do not use, install, modify or redistribute this NVIDIA + software. + . + In consideration of your agreement to abide by the following terms, and + subject to these terms, NVIDIA grants you a personal, non-exclusive + license, under NVIDIA's copyrights in this original NVIDIA software (the + "NVIDIA Software"), to use, reproduce, modify and redistribute the + NVIDIA Software, with or without modifications, in source and/or binary + forms; provided that if you redistribute the NVIDIA Software, you must + retain the copyright notice of NVIDIA, this notice and the following + text and disclaimers in all such redistributions of the NVIDIA Software. + Neither the name, trademarks, service marks nor logos of NVIDIA + Corporation may be used to endorse or promote products derived from the + NVIDIA Software without specific prior written permission from NVIDIA. + Except as expressly stated in this notice, no other rights or licenses + express or implied, are granted by NVIDIA herein, including but not + limited to any patent rights that may be infringed by your derivative + works or by other works in which the NVIDIA Software may be + incorporated. No hardware is licensed hereunder. + . + THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, + INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, + NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR + ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER + PRODUCTS. + . + IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, + INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY + OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE + NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, + TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF + NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: FTL + The FreeType Project LICENSE + ---------------------------- + . + 2006-Jan-27 + . + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + . + . + . + Introduction + ============ + . + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + . + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + . + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + . + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + . + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + . + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + . + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + . + . + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + . + """ + Portions of this software are copyright © The FreeType + Project (https://freetype.org). All rights reserved. + """ + . + Please replace with the value from the FreeType version you + actually use. + . + . + Legal Terms + =========== + . + 0. Definitions + -------------- + . + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + . + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + . + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + . + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + . + 1. No Warranty + -------------- + . + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + . + 2. Redistribution + ----------------- + . + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + . + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + . + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + . + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + . + 3. Advertising + -------------- + . + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + . + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + . + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + . + 4. Contacts + ----------- + . + There are two mailing lists related to FreeType: + . + o freetype@nongnu.org + . + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + . + o freetype-devel@nongnu.org + . + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + . + Our home page can be found at + . + https://freetype.org + +License: HarfBuzz + HarfBuzz is licensed under the so-called "Old MIT" license. Details follow. + For parts of HarfBuzz that are licensed under different licenses see individual + files names COPYING in subdirectories where applicable. + . + Copyright (C) 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 Google, Inc. + Copyright (C) 2018,2019,2020 Ebrahim Byagowi + Copyright (C) 2019,2020 Facebook, Inc. + Copyright (C) 2012 Mozilla Foundation + Copyright (C) 2011 Codethink Limited + Copyright (C) 2008,2010 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 Keith Stribley + Copyright (C) 2009 Martin Hosken and SIL International + Copyright (C) 2007 Chris Wilson + Copyright (C) 2005,2006,2020,2021 Behdad Esfahbod + Copyright (C) 2005 David Turner + Copyright (C) 2004,2007,2008,2009,2010 Red Hat, Inc. + Copyright (C) 1998-2004 David Turner and Werner Lemberg + . + For full copyright notices consult the individual files in the package. + . + . + Permission is hereby granted, without written agreement and without + license or royalty fees, to use, copy, modify, and distribute this + software and its documentation for any purpose, provided that the + above copyright notice and the following two paragraphs appear in + all copies of this software. + . + IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + . + THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +License: IJG + The authors make NO WARRANTY or representation, either express or implied, + with respect to this software, its quality, accuracy, merchantability, or + fitness for a particular purpose. This software is provided "AS IS", and you, + its user, assume the entire risk as to its quality and accuracy. + . + This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding. + All Rights Reserved except as specified below. + . + Permission is hereby granted to use, copy, modify, and distribute this + software (or portions thereof) for any purpose, without fee, subject to these + conditions: + (1) If any part of the source code for this software is distributed, then this + README file must be included, with this copyright and no-warranty notice + unaltered; and any additions, deletions, or changes to the original files + must be clearly indicated in accompanying documentation. + (2) If only executable code is distributed, then the accompanying + documentation must state that "this software is based in part on the work of + the Independent JPEG Group". + (3) Permission for use of this software is granted only if the user accepts + full responsibility for any undesirable consequences; the authors accept + NO LIABILITY for damages of any kind. + . + These conditions apply to any software derived from or based on the IJG code, + not just to the unmodified library. If you use our work, you ought to + acknowledge us. + . + Permission is NOT granted for the use of any IJG author's name or company name + in advertising or publicity relating to this software or products derived from + it. This software may be referred to only as "the Independent JPEG Group's + software". + . + We specifically permit and encourage the use of this software as the basis of + commercial products, provided that all warranty or liability claims are + assumed by the product vendor. + +License: MPL-2.0 + Mozilla Public License Version 2.0 + ================================== + . + 1. Definitions + -------------- + . + 1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + . + 1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + . + 1.3. "Contribution" + means Covered Software of a particular Contributor. + . + 1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + . + 1.5. "Incompatible With Secondary Licenses" + means + . + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + . + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + . + 1.6. "Executable Form" + means any form of the work other than Source Code Form. + . + 1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + . + 1.8. "License" + means this document. + . + 1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + . + 1.10. "Modifications" + means any of the following: + . + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + . + (b) any new file in Source Code Form that contains any Covered + Software. + . + 1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + . + 1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + . + 1.13. "Source Code Form" + means the form of the work preferred for making modifications. + . + 1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + . + 2. License Grants and Conditions + -------------------------------- + . + 2.1. Grants + . + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + . + (a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + . + (b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + . + 2.2. Effective Date + . + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + . + 2.3. Limitations on Grant Scope + . + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + . + (a) for any code that a Contributor has removed from Covered Software; + or + . + (b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + . + (c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + . + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + . + 2.4. Subsequent Licenses + . + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + . + 2.5. Representation + . + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights + to grant the rights to its Contributions conveyed by this License. + . + 2.6. Fair Use + . + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + . + 2.7. Conditions + . + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted + in Section 2.1. + . + 3. Responsibilities + ------------------- + . + 3.1. Distribution of Source Form + . + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + . + 3.2. Distribution of Executable Form + . + If You distribute Covered Software in Executable Form then: + . + (a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + . + (b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + . + 3.3. Distribution of a Larger Work + . + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + . + 3.4. Notices + . + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, + or limitations of liability) contained within the Source Code Form of + the Covered Software, except that You may alter any license notices to + the extent required to remedy known factual inaccuracies. + . + 3.5. Application of Additional Terms + . + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + . + 4. Inability to Comply Due to Statute or Regulation + --------------------------------------------------- + . + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Software due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description must + be placed in a text file included with all distributions of the Covered + Software under this License. Except to the extent prohibited by statute + or regulation, such description must be sufficiently detailed for a + recipient of ordinary skill to be able to understand it. + . + 5. Termination + -------------- + . + 5.1. The rights granted under this License will terminate automatically + if You fail to comply with any of its terms. However, if You become + compliant, then the rights granted under this License from a particular + Contributor are reinstated (a) provisionally, unless and until such + Contributor explicitly and finally terminates Your grants, and (b) on an + ongoing basis, if such Contributor fails to notify You of the + non-compliance by some reasonable means prior to 60 days after You have + come back into compliance. Moreover, Your grants from a particular + Contributor are reinstated on an ongoing basis if such Contributor + notifies You of the non-compliance by some reasonable means, this is the + first time You have received notice of non-compliance with this License + from such Contributor, and You become compliant prior to 30 days after + Your receipt of the notice. + . + 5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + . + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all + end user license agreements (excluding distributors and resellers) which + have been validly granted by You or Your distributors under this License + prior to termination shall survive termination. + . + ************************************************************************ + * * + * 6. Disclaimer of Warranty * + * ------------------------- * + * * + * Covered Software is provided under this License on an "as is" * + * basis, without warranty of any kind, either expressed, implied, or * + * statutory, including, without limitation, warranties that the * + * Covered Software is free of defects, merchantable, fit for a * + * particular purpose or non-infringing. The entire risk as to the * + * quality and performance of the Covered Software is with You. * + * Should any Covered Software prove defective in any respect, You * + * (not any Contributor) assume the cost of any necessary servicing, * + * repair, or correction. This disclaimer of warranty constitutes an * + * essential part of this License. No use of any Covered Software is * + * authorized under this License except under this disclaimer. * + * * + ************************************************************************ + . + ************************************************************************ + * * + * 7. Limitation of Liability * + * -------------------------- * + * * + * Under no circumstances and under no legal theory, whether tort * + * (including negligence), contract, or otherwise, shall any * + * Contributor, or anyone who distributes Covered Software as * + * permitted above, be liable to You for any direct, indirect, * + * special, incidental, or consequential damages of any character * + * including, without limitation, damages for lost profits, loss of * + * goodwill, work stoppage, computer failure or malfunction, or any * + * and all other commercial damages or losses, even if such party * + * shall have been informed of the possibility of such damages. This * + * limitation of liability shall not apply to liability for death or * + * personal injury resulting from such party's negligence to the * + * extent applicable law prohibits such limitation. Some * + * jurisdictions do not allow the exclusion or limitation of * + * incidental or consequential damages, so this exclusion and * + * limitation may not apply to You. * + * * + ************************************************************************ + . + 8. Litigation + ------------- + . + Any litigation relating to this License may be brought only in the + courts of a jurisdiction where the defendant maintains its principal + place of business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. + Nothing in this Section shall prevent a party's ability to bring + cross-claims or counter-claims. + . + 9. Miscellaneous + ---------------- + . + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides + that the language of a contract shall be construed against the drafter + shall not be used to construe this License against a Contributor. + . + 10. Versions of the License + --------------------------- + . + 10.1. New Versions + . + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + . + 10.2. Effect of New Versions + . + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + . + 10.3. Modified Versions + . + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + . + 10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses + . + If You choose to distribute Source Code Form that is Incompatible With + Secondary Licenses under the terms of this version of the License, the + notice described in Exhibit B of this License must be attached. + . + Exhibit A - Source Code Form License Notice + ------------------------------------------- + . + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + . + If it is not possible or desirable to put the notice in a particular + file, then You may include the notice in a location (such as a LICENSE + file in a relevant directory) where a recipient would be likely to look + for such a notice. + . + You may add additional accurate notices of copyright ownership. + . + Exhibit B - "Incompatible With Secondary Licenses" Notice + --------------------------------------------------------- + . + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + +License: MIT-0 + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License: OFL-1.1 + PREAMBLE + The goals of the Open Font License (OFL) are to stimulate worldwide + development of collaborative font projects, to support the font creation + efforts of academic and linguistic communities, and to provide a free and + open framework in which fonts may be shared and improved in partnership + with others. + . + The OFL allows the licensed fonts to be used, studied, modified and + redistributed freely as long as they are not sold by themselves. The + fonts, including any derivative works, can be bundled, embedded, + redistributed and/or sold with any software provided that any reserved + names are not used by derivative works. The fonts and derivatives, + however, cannot be released under any other type of license. The + requirement for fonts to remain under this license does not apply + to any document created using the fonts or their derivatives. + . + DEFINITIONS + "Font Software" refers to the set of files released by the Copyright + Holder(s) under this license and clearly marked as such. This may + include source files, build scripts and documentation. + . + "Reserved Font Name" refers to any names specified as such after the + copyright statement(s). + . + "Original Version" refers to the collection of Font Software components as + distributed by the Copyright Holder(s). + . + "Modified Version" refers to any derivative made by adding to, deleting, + or substituting -- in part or in whole -- any of the components of the + Original Version, by changing formats or by porting the Font Software to a + new environment. + . + "Author" refers to any designer, engineer, programmer, technical + writer or other person who contributed to the Font Software. + . + PERMISSION & CONDITIONS + Permission is hereby granted, free of charge, to any person obtaining + a copy of the Font Software, to use, study, copy, merge, embed, modify, + redistribute, and sell modified and unmodified copies of the Font + Software, subject to the following conditions: + . + 1) Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + . + 2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + . + 3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + . + 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + . + 5) The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + . + TERMINATION + This license becomes null and void if any of the above conditions are + not met. + . + DISCLAIMER + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE. + +License: Unicode + COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) + . + Copyright (C) 1991-2020 Unicode, Inc. All rights reserved. + Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + . + Permission is hereby granted, free of charge, to any person obtaining + a copy of the Unicode data files and any associated documentation + (the "Data Files") or Unicode software and any associated documentation + (the "Software") to deal in the Data Files or Software + without restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, and/or sell copies of + the Data Files or Software, and to permit persons to whom the Data Files + or Software are furnished to do so, provided that either + (a) this copyright and permission notice appear with all copies + of the Data Files or Software, or + (b) this copyright and permission notice appear in associated + Documentation. + . + THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF + ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS + NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL + DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THE DATA FILES OR SOFTWARE. + . + Except as contained in this notice, the name of a copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in these Data Files or Software without prior + written authorization of the copyright holder. + +License: Unlicense + This is free and unencumbered software released into the public domain. + . + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + . + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + . + For more information, please refer to + +License: WOL + The Wide Open License (WOL) + . + Permission to use, copy, modify, distribute and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice and this license appear in all source copies. + THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF + ANY KIND. See https://dspguru.com/wide-open-license/ for more information. + +License: X11 + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that\n the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + . + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + +License: Zlib + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + . + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + . + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. diff --git a/assets-source/phase6/licenses/GODOT-LICENSE.txt b/assets-source/phase6/licenses/GODOT-LICENSE.txt new file mode 100644 index 0000000..0e3ba08 --- /dev/null +++ b/assets-source/phase6/licenses/GODOT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). +Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets-source/phase6/revisions/before-polish.tar.gz b/assets-source/phase6/revisions/before-polish.tar.gz new file mode 100644 index 0000000..a82313c Binary files /dev/null and b/assets-source/phase6/revisions/before-polish.tar.gz differ diff --git a/assets-source/phase7/revisions/before-high-detail.tar.gz b/assets-source/phase7/revisions/before-high-detail.tar.gz new file mode 100644 index 0000000..15f5640 Binary files /dev/null and b/assets-source/phase7/revisions/before-high-detail.tar.gz differ diff --git a/assets-source/phase8/revisions/before-expedition.tar.gz b/assets-source/phase8/revisions/before-expedition.tar.gz new file mode 100644 index 0000000..51334b6 Binary files /dev/null and b/assets-source/phase8/revisions/before-expedition.tar.gz differ diff --git a/assets-source/phase9/revisions/before-second-faction.tar.gz b/assets-source/phase9/revisions/before-second-faction.tar.gz new file mode 100644 index 0000000..684c2cb Binary files /dev/null and b/assets-source/phase9/revisions/before-second-faction.tar.gz differ diff --git a/assets/Champions_of_Luneraria_Claude_Code_Masterprompt.md b/assets/Champions_of_Luneraria_Claude_Code_Masterprompt.md new file mode 100644 index 0000000..f6e792e --- /dev/null +++ b/assets/Champions_of_Luneraria_Claude_Code_Masterprompt.md @@ -0,0 +1,265 @@ +# Champions of Luneraria – Masterauftrag für Claude Code + +Modellvorgabe: Claude Opus 5.5. +Vorgesehene Denkstufe: Max, außerhalb dieses Prompts in Claude Code einstellen. +Engineentscheidung: vorhandenes Godot-Projekt weiterentwickeln; kein Unreal-Neustart. +Zielplattformen: native Anwendungen für Fedora 44 und Windows 11. +Assetproduktion: Blender; vorhandene Assets und Generierungsskripte zuerst wiederverwenden. + +## 1. Auftrag und Arbeitsweise + +Entwickle das bestehende Spiel „Saumwacht“ im vorhandenen Repository zu „Champions of Luneraria“ weiter: einem eigenständigen 3D-Team-Autobattler mit drei Lanes, MOBA-Kartenstruktur, entwickelbaren Helden und taktischer Bossjagd. + +Das ist eine beauftragte Änderung des Spielprinzips, kein bloßer Skin und kein Neubau auf leerer Grundlage. Erhalte funktionierende Assets, Pipelines und geeignete Systeme. Verändere die bisherigen Regeln dort ausdrücklich, wo dieser Auftrag sie ersetzt. + +Arbeite als verantwortlicher Game Developer und Technical Artist. Prüfe zuerst den Bestand, triff begründete Detailentscheidungen und implementiere anschließend tatsächlich. Beschränke dich nicht auf Konzepte, Gerüste oder einen Abschlussbericht ohne spielbares Ergebnis. + +Arbeite in überprüfbaren Meilensteinen. Überspringe keine Abnahme, um möglichst viele Funktionen als begonnen aufzulisten. Nutze verfügbare Unteragenten nur für sauber getrennte Teilaufgaben und vermeide konkurrierende Änderungen an denselben Dateien. Bei einem echten Werkzeug-, Berechtigungs- oder Kontextlimit hinterlasse einen startfähigen Zwischenstand und einen präzisen Fortsetzungspunkt. Behaupte nicht, das vollständige Ziel sei erreicht, wenn nur ein Teil implementiert ist. + +Die Einstellung Max ist keine Aufforderung zu endlosen Architekturüberlegungen. Dokumentiere Entscheidungen, Risiken und Prüfergebnisse knapp und nachvollziehbar. Routinemäßige Entscheidungen benötigen keine Rückfrage. Änderungen an den unten als verbindlich bezeichneten Produktregeln benötigen dagegen eine ausdrückliche Entscheidung des Auftraggebers. + +## 2. Bestandsaufnahme, Quellenrangfolge und Schutz + +Untersuche Repository, Git-Status, Projektwurzel, project.godot, CLAUDE.md, README, Szenen, Autoloads, Ressourcen, Tests, Exportskripte und Blender-Pipeline. Prüfe tatsächliche Godot-/Blender-Versionen und verfügbare Exportvorlagen. Aktualisiere keine Engine pauschal auf eine vermeintlich bessere Version. + +Als letzter Bericht ist Phase 20A mit Demo 0.15.0 bekannt. Ältere README-Dateien und Logs können noch 0.14.0 beschreiben. Prüfe auch, ob inzwischen 20B oder weitere Arbeiten vorliegen. Setze keinen neueren Arbeitsstand zurück. + +Quellenrangfolge: +1. Verbindliche Regeln dieses Auftrags. +2. Spätere ausdrücklich bestätigte Nutzerentscheidungen. +3. Tatsächlich vorhandener Code und aktuelle Projektdokumentation. +4. Ältere Berichte und Illustrationen als Hintergrund. + +Konzeptbilder sind Stil- und Kompositionsvorlagen, keine ausführbare Regelspezifikation. Übernimm daraus keine versehentlich falsche Turmzahl, unverbundenen Wege, Versionsangaben oder Aussage zur falschen Boss-Angriffsrichtung. Suche bereitgestellte Bilder im Projekt; behaupte nicht, Bilder oder externe Chatverläufe gesehen zu haben, die dort nicht vorliegen. + +Dokumentiere vorhandene uncommittete Änderungen. Sichere den Zustand einschließlich benötigter unversionierter Quellen nachvollziehbar. Nutze einen eigenen Entwicklungsbranch, soweit der Zustand das ohne Eingriff in fremde Arbeit erlaubt. Kein reset --hard, kein git clean, kein pauschales Stash und kein Überschreiben fremder Änderungen. Commits enthalten nur diesem Auftrag zugehörige Änderungen. + +Beschränke Schreibzugriffe auf den bestätigten Projektworkspace und dessen dokumentierte Build-/Dokumentationsverzeichnisse. Keine privaten Dateien, Zugangsdaten, systemweiten Paketinstallationen, Firewalländerungen, kostenpflichtigen Dienste oder Veröffentlichung ohne erforderliche Zustimmung. Vorhandene Benutzeroptionen dürfen bei der Umbenennung nicht verloren gehen. + +## 3. Verbindliche Produktregeln + +- Titel: Champions of Luneraria. +- Zwei Teams mit jeweils drei eigenständigen Spielerrollen. +- Drei zusammenhängende Lanes: Top, Mid und Bottom. +- Kämpfe sind automatisch; keine direkte MOBA-Heldensteuerung und kein manuelles Last-Hitting. +- Eine Partie endet durch Zerstörung eines Ancient-Kerns. Es gibt keine feste maximale Rundenzahl und keinen Sieg nach Welle 8, 20, 50 oder einer anderen Grenze. +- Keine Entscheidung nach verbleibenden Kern-Lebenspunkten und kein Zeitlimit, das einen Sieger ermittelt. +- Monsterwellen werden mit jeder Welle stärker. +- Je Team und Lane zwei Lanetürme; zusätzliche Türme schützen den Ancient. +- Normale Truppen werden dauerhaft gekauft und aufgerüstet, erhalten aber weder individuelles Levelsystem noch Items. +- Besondere Helden werden gekauft, sammeln innerhalb der Partie Erfahrung und können mit Items und Talenten entwickelt werden. +- Angriffschampions werden mit Gold als einmalige Verstärkung einer Angriffswelle gekauft. +- Besiegte Monster und Angriffschampions geben Gold. +- Eine gemeinsame Bossgrotte bindet Einheiten, die dafür ihre Lane verlassen müssen. +- Nach erfolgreicher Eroberung verstärkt der Boss einmalig den Angriff des siegreichen Teams in der folgenden Runde gegen das gegnerische Team. +- Der entsandte Boss gibt dem verteidigenden Team bei seinem Tod deutlich mehr Gold als ein normaler Gegner. +- Nach einem Bosssieg ist die Grotte drei vollständige Runden gesperrt. +- Vorhandene Assets werden bevorzugt erhalten und weiterverwendet. +- Inhaltsziel: Elfen, Trolle, Zwerge, Menschen, Feen, Orks und Biestmenschen. Bestehende Wesen und Bünde dürfen sinnvoll Bestandteil dieser Welt bleiben. +- Ziel ist taktische Wiederspielbarkeit, nicht bloß eine größere Menge austauschbarer Einheiten. + +Ein manueller Testabbruch ist kein regulärer Sieg. Werden beide Kerne im selben autoritativen Simulationsschritt zerstört, gilt als dokumentierte Startregel ein Unentschieden. Keine Bevorzugung aufgrund von Array-, Render- oder Netzwerkreihenfolge. Ein technischer Abbruch ist kein Kern-Sieg. + +## 4. Festgelegte Arbeitsannahmen für den ersten Prototyp + +Diese Punkte konkretisieren bisher offene Details. Dokumentiere sie ausdrücklich als anpassbare Designentscheidungen, nicht als ursprüngliche Nutzerzitate: + +A. Dauerhafte Truppen und Helden rücken mit den eigenen Monsterwellen über ihre zugewiesene Lane vor. Nach gewonnenen Gefechten greifen sie zulässige gegnerische Gebäude an. Es sind nicht nur drei isolierte Verteidigungsbretter. + +B. Jeder Spieler verwaltet eigenes Gold und eine eigene Armee. Eine Lane ist seine anfängliche Zuständigkeit; Unterstützung anderer Lanes bleibt möglich. Die Teamzugehörigkeit ist unabhängig vom Fantasyvolk und vom gewählten Bund. + +C. Pro Spieler ist zunächst ein aktiver Held mit drei Itemplätzen erlaubt. Mehrere unterschiedliche Helden stehen zur Wahl. Normale Truppen bleiben relevant; der Held darf nicht die gesamte Armee ersetzen. + +D. Pro Team gibt es genau zwei gemeinsame Basistürme: insgesamt acht Türme je Team, sechzehn auf der Karte, plus zwei Ancient-Kerne. + +E. Die bestehende Arbeiter-/Funkenökonomie wird im neuen Modus zunächst nicht parallel betrieben. Gold finanziert Armee, Aufwertungen, Helden, Items und Angriffschampions. Bewahre alte Inhalte auf, ohne zwei konkurrierende Wirtschaftsmodelle zu vermischen. + +F. Der erste Modus ist eine echte Sechs-Spieler-Simulation mit einem Menschen und fünf Bots. Darauf folgt ein klar abgegrenzter Netzwerkmeilenstein. Bots allein sind kein implementierter Online-Multiplayer. + +## 5. Rundenablauf ohne Partierundenlimit + +Verwende die eindeutige Folge Planung → verbindliche Befehle → automatischer Kampf → Abrechnung → nächste Planung. Die Wellennummer steigt weiter, solange beide Kerne bestehen. + +In der Planung: kaufen, aufwerten, ausrüsten, Formation setzen, Truppen zu einer Lane oder Grotte zuweisen und Verstärkungen buchen. Beim Phasenwechsel werden Befehle atomar geprüft und verbindlich übernommen. Nicht während des Kampfes beliebig umdisponieren. + +Für den Prototyp starten Armeen und Wellen je Runde an festen, symmetrischen lanegebundenen Aufmarschbereichen ihrer Basis. Formationspositionen sind lokale Offsets zur Laufrichtung. Keine willkürlichen Front-Teleports. Geländelängen und Bewegungsgeschwindigkeit müssen zulassen, dass Angriffe innerhalb einer Kampfphase die relevanten Gebäude erreichen. + +Dauerhafte Truppen und Helden kehren nach der Kampfphase in den eigenen Bestand zurück. Sie beginnen das nächste Gefecht geheilt; Helden behalten Erfahrung, Talente und Items, Truppen ihre Aufwertungen. Temporäre Effekte und Fähigkeitencooldowns werden nach einer ausdrücklich dokumentierten gemeinsamen Regel zurückgesetzt. Keine Itemduplikation durch diesen Reset. + +Monsterwellen, einmalige Angriffschampions und entsandte Bosse sind temporäre Kampfinstanzen und werden nicht zu dauerhaftem Besitz. Nicht getötete temporäre Einheiten verschwinden bei regulärem Rundenabschluss ohne Killbelohnung. Türme und Kerne behalten ihren Schaden; zerstörte Gebäude kehren nicht zurück. + +Ein konfigurierbares Zeitfenster für die einzelne Kampfphase darf gegenseitige Heilungs- oder Wegfindungs-Endlosschleifen verhindern. Es beendet nur diese Kampfphase, niemals die Partie, verteilt keine erfundenen Kills und verursacht keinen unsichtbaren Kernschaden. Dokumentiere die Auflösung aller verbleibenden Einheiten. Prüfe mit der tatsächlichen Karte, dass der Wert Angriffe nicht systematisch vor der Basis abschneidet. + +Offline kann die Planung auf den Spieler warten. Im Netzwerk entscheiden der Server und ein synchroner Ready-/Planungsablauf. Ein Client darf nicht allein für alle pausieren oder die Simulation beschleunigen. Laneverlust eliminiert keinen Spieler: Er kann weiter aufbauen, die Basis verteidigen und Verbündete unterstützen. + +## 6. Karte und Gebäude + +Baue eine eigenständige, gut lesbare MOBA-inspirierte Karte. Ausgangsentwurf: eine Basis im Südwesten, die andere im Nordosten; Top über den oberen/linken Korridor, Bottom über den unteren/rechten, Mid als direkte Verbindung. Keine Kopie einer bestehenden kommerziellen Karte. + +Platziere die Bossgrotte nahe dem Zentrum, aber seitlich außerhalb der Mid-Lane. Beide Teams erhalten funktional gleichwertige Zugänge. Keine normale Monsterwelle läuft versehentlich durch die Grotte. Lanewechsel und Grottenzuweisung erfolgen über getrennte Auftragswege, nicht über unbeabsichtigte Navmesh-Abkürzungen. + +Turmregeln: äußerer vor innerem Turm der jeweiligen Lane. Eine vollständig durchbrochene Lane eröffnet den Zugang zur Basis; nicht erst die Zerstörung aller sechs Lanetürme. Beide Basistürme müssen fallen, bevor der Ancient verwundbar wird. Intakte Türme anderer Lanes bleiben bestehen und funktionieren weiter. + +Sperren gelten auch für Fernkampf, Flächenschaden, Bossangriffe und sonstige Spezialfähigkeiten. Keine Umgehung durch Beschuss hinter ein unzerstörtes Vorgängergebäude. Einheiten wählen nach einem zerstörten Ziel korrekt neu, ohne durch Sperren zu laufen oder endlos ein unerreichbares Ziel anzusteuern. + +Nutze vorhandene Felsen, Vegetation, Materialien, Kerne und Bauwerke modular. Erstelle zuerst eine funktionale Karte mit echten Bestandsassets; ersetze Hilfsgeometrie anschließend gezielt. Die endgültige Darstellung darf kein grauer Blockout bleiben. + +Prüfe Kartensymmetrie funktional: Strecken, Engstellen, Angriffsdistanzen, Aufmarschflächen und Grottenzugänge. Unterschiedliche Dekoration darf kein Team benachteiligen. + +## 7. Unbegrenzt fortgesetzte und stärker werdende Wellen + +Entkopple Wellenerzeugung von der alten endlichen Expeditionsliste. Verwende datengetriebene Zusammensetzungen und nachvollziehbare Skalierung. Verfügbare Gegnertypen können rotieren; die Leistungsfähigkeit einer vergleichbaren Welle nimmt mit ihrem Index zu. + +Keine unbegrenzt wachsende Zahl gleichzeitig aktiver Kreaturen. Begrenze die sichtbare Einheitenmenge durch offengelegte Regeln und skaliere später stärker über Werte, Rollen und stärkere Varianten. Ein späterer Index darf keinen Arrayfehler, Zahlenüberlauf oder NaN erzeugen. + +Monster-, Gold-, Helden- und Turmskalierung müssen zusammenpassen. Definiere eine Langpartie-Balance, bei der bloßes endloses Einigeln nicht die einzig vernünftige Spielweise ist. Erzwinge aber keinen Sieg über einen verborgenen Timer, automatischen Gebäudeverfall oder einen letzten Wellenindex. + +Führe Belastungstests mit hohen Indizes und lange laufenden Zuständen getrennt von normaler Balance durch. Ein QA-Lauf darf eine Testobergrenze besitzen; ein dort nicht beendetes Spiel wird als „Testlimit erreicht / Partie nicht abgeschlossen“ protokolliert, nicht als reguläres Unentschieden oder Sieg. Eine numerische Testsperre darf niemals zur Produktregel werden. + +## 8. Gold, Einheiten und Angriffschampions + +Trenne persistente Besitzobjekte von ihren temporären Kampfinstanzen. Jeder Kauf, jede Aufwertung und jede Zuweisung benötigt eindeutige IDs und validierte Kosten. Sichtbarkeit oder UI-Zustand dürfen Besitz nicht erzeugen. + +Starte mit persönlichem Grundeinkommen pro Runde und eindeutig definierten Killbelohnungen. Kein Last-Hit-Wettbewerb: Pro gegnerischem Todesereignis wird genau eine Gesamtbelohnung verteilt, unabhängig davon, ob Truppe, Held, Projektil oder Turm tötet. + +Konfigurierbarer Startvorschlag: Lane-Killgold zur Hälfte an den zuständigen Lane-Spieler, zur Hälfte gleichmäßig ans eigene Team. Gebäudebelohnungen und das Kopfgeld eines entsandten Bosses werden gleichmäßig im Team verteilt. Definiere verlustfreie Ganzzahl-/Restverteilung. Niemals die volle Belohnung versehentlich dreimal auszahlen. + +Eigene Einheiten, Attrappen, Reset-Despawn und beschworene Endlosgegner dürfen keine Goldfarmen sein. Helden und persistente Truppen erhalten zunächst kein zusätzliches Killkopfgeld; Monster und Angriffschampions schon. Der initiale Grottensieg belohnt primär mit der Bossentsendung, nicht mit einem zweiten riesigen Goldpaket. + +Angriffschampions besitzen unterschiedliche Rollen, beispielsweise Schutz, Belagerung oder Druck auf Unterstützer. Sie sind verbrauchbare Investitionen; sie erhöhen nicht automatisch dauerhaft das Einkommen. Käufe in Runde n buchen den Einsatz für Runde n+1. Bereits bezahlte Buchungen werden zu Beginn der nächsten Planung angekündigt und anschließend nicht beliebig kostenlos zwischen Lanes verschoben. + +Lege Anfangsgold, Einkommen, Kosten, Kopfgelder, Versorgungsgrenzen und Verkaufsregeln zentral in Balanceressourcen ab. Begründe Startwerte anhand des bestehenden Spiels und prüfe sie. Keine versteckten Sondergelder für Bots oder Screenshots der normalen Partie. + +## 9. Helden, Erfahrung, Talente und Items + +Implementiere ein echtes, vom normalen Truppenupgrade getrenntes Heldensystem. Erfahrung entsteht aus transparent definierter Teilnahme an Gefechten und Rundenfortschritt, nicht aus zufälligen letzten Treffern. Unterstützende Helden dürfen nicht systematisch leer ausgehen. + +Talente sollen Aufgaben verändern: beispielsweise Eigenschutz gegen Gruppenschutz oder Einzelzielwirkung gegen Flächenwirkung. Anfangs wenige klar unterscheidbare Entscheidungen statt eines großen, bedeutungslosen Zahlenbaums. + +Drei Itemplätze, zunächst permanente Items ohne Verbrauchsgegenstands-Komplexität. Items sind in der Planung ausrüstbar. Definiere Stapelbarkeit, Einzigartigkeit, Verkauf, Voraussetzungen und Event-Reihenfolge. Effekte dürfen sich nicht unbegrenzt gegenseitig auslösen; keine Heilungs-/Schild-/Schadensschleifen. + +Helden kämpfen automatisch. Für den Spieler verständliche Zielprioritäten sind zulässig; keine manuell zu bedienende MOBA-Aktionsleiste. Positionierung, Armee, Talent und Itemwahl steuern den Einsatz. + +Kein permanenter Stärkevorteil zwischen Partien. Level und Ausrüstung gehören zur laufenden Partie. Teste ausdrücklich, dass Neustart und neue Partie keinen Fortschritt unbeabsichtigt übernehmen. + +Für den ersten vollständigen Mechaniktest reichen drei funktional verschiedene Helden, sechs sinnvolle Items, mindestens sechs normale Truppentypen und drei Angriffschampions. Dafür bevorzugt vorhandene Modelle nutzen. Kennzeichne vorläufige Rollenzuordnungen intern, statt Bestandsmodelle fälschlich als bereits neu erstellte Völker auszugeben. + +## 10. Bossgrotte und erbeuteter Boss + +Implementiere einen eigenständigen, testbaren Bosszustand. Unterscheide neutralen Boss, Expedition, erfolgreichen Besitzanspruch, angekündigte Entsendung, entsandte Kampfinstanz und Wiederverfügbarkeit. + +Einheiten werden in der Planung verbindlich abgezogen und fehlen ihrer Lane für die gesamte anschließende Kampfphase. Auch ein schneller Grottensieg schickt sie nicht noch in derselben Runde zurück auf eine Lane. + +Arbeitsregel für gleichzeitige Expeditionen: Zuerst kämpfen die beiden Expeditionen gegeneinander. Nur die überlebende Gruppe kämpft mit den verbliebenen Lebenspunkten gegen den neutralen Boss. Scheitert sie oder läuft die Phase ab, gibt es keine Bossbelohnung. Keine Entscheidung anhand von Ping oder letztem Treffer auf einen gemeinsam geschlagenen Boss. + +Nach einem gescheiterten Versuch startet der neutrale Boss beim nächsten Versuch wieder vollständig hergestellt. Nach einem Sieg gehört genau eine Entsendung dem erfolgreichen Team. Keine duplizierte Belohnung durch wiederholte Signale oder Netzwerkpakete. + +Der erfolgreiche Anspruch wählt bei der Abrechnung eine Ziellane: zunächst der beitragende Lane-Spieler mit dem höchsten eingesetzten Armeekaufwert, bei Gleichstand eine stabile Slotreihenfolge. Kein unauflösbarer Teamdialog. Die Auswahl wird für die nächste Planung angezeigt; ohne Eingabe gilt eine dokumentierte Default-Lane. Online validiert der Server die Zuständigkeit. + +Wichtig: Der Boss unterstützt die EIGENE Angriffswelle des erobernden Teams und läuft zum GEGNERISCHEN Ancient. Er unterstützt nicht die Gegner des Teams, das ihn besiegt hat. + +Sieg in Runde 6 bedeutet Einsatz in Runde 7, Grotte gesperrt in Runde 7, 8 und 9, erneut bekämpfbar ab Runde 10. Berechne daraus next_available_round; keine unklare, mehrfach pro Frame heruntergezählte Sperre. Die Sperre hängt am Grottensieg, nicht am späteren Tod des entsandten Bosses. + +Der Boss wird automatisch in der unmittelbar folgenden Runde entsandt, nicht unbegrenzt gespeichert. Stärke und hohes Kopfgeld richten sich nach der Einsatzwelle. Ein vollständiger Vorabhinweis nennt Lane und Belohnung. Reguläre Gebäude-Sperren gelten unverändert. + +Vergleiche mindestens erfolgreiche und gescheiterte Expedition, umkämpfte Grotte, abgewehrten Boss, erfolgreichen Bossdurchbruch und absichtlich riskante Überinvestition. Eine Bossstrategie darf nicht durch kostenlose Sofortrückkehr, Doppelbelohnungen oder verschwiegenes Goldrisiko dominant werden. + +## 11. Völker, Bestandsassets und Blender + +Erstelle eine Wiederverwendungsmatrix: Asset, Pfad, Quelle, Rig/Clips, bisherige Rolle, neue Rolle, Materialzustand und notwendiger Eingriff. Erhalte besonders die ausgearbeiteten Modelle wie Ringborke, Funkenleser, Basaltbastion, Quellgeflecht, Funkenlanze, Glasballiste und die Kernkristalle, soweit im tatsächlichen Stand vorhanden. + +Die sieben gewünschten Völker sind das Inhaltsziel, nicht sieben sofort vollständig isolierte Fraktionen. Trenne Volk, Bund, Klasse und Kampfrolle in den Daten. Menschen, Elfen, Zwerge, Trolle, Feen, Orks und Biestmenschen müssen später ergänzbar sein, ohne sieben parallele Kampfsysteme zu erzeugen. Vermeide pauschale Sammelboni als einzige Synergie. + +Nach dem spielbaren Kern ergänze die fehlenden Völker schrittweise mit mindestens einem erkennbar eigenständigen Repräsentanten und einem sinnvollen Entwicklungsplan. Ersetze keine bereits geeignete Figur nur wegen des neuen Titels. Erfinde keine fertige Modellproduktion, wenn nur Dateneinträge existieren. + +Blender bleibt das Autorenwerkzeug. Nutze vorhandene Python-Generatoren und reproduzierbare Exporte; speichere editierbare Quellen und GLB-Laufzeitassets. Spieler benötigen weder Blender noch den Godot-Editor. Laufzeitgenerierung darf keine versteckte lokale Blender-Installation voraussetzen. + +Erhalte Skalierung, Pivot, Knochen, Animationen, Materialzuordnung und authored Attack-Timing. Die Simulation entscheidet über Schaden und Treffer; Kamerasichtbarkeit, Animations-LOD oder ausgeblendete Modelle dürfen den Kampf nicht verändern. Synchronisiere die Darstellung mit den tatsächlichen Kampfereignissen. + +Keine Mindestpolygonzahl als Qualitätsbeweis. Prüfe getrennt Assetidentität, technische Integrität und Aussehen in Nahaufnahme sowie Spielkamera. Keine automatische Neuschreibung der Freigabereferenz durch denselben Test, der die Referenz prüfen soll. Bestehende gute Modelle nicht pauschal vereinfachen; keine zusätzliche Geometrie allein zum Erfüllen einer Kennzahl. + +## 12. Godot-Architektur, KI und Netzwerk + +Behalte Godot und den vorhandenen Haupt-Renderer. Erhalte den bestehenden Kompatibilitätsmodus mit transparent dokumentierten visuellen Unterschieden. Keine Unreal-Migration und kein paralleles Engine-Projekt. + +Trenne Regeln, Darstellung und Eingabe. Passe vorhandene Komponenten an, statt um jeden Preis ein neues Framework oder ECS einzuführen. Benötigte Verantwortlichkeiten sind unter anderem Matchzustand, Team/Spieler, Lanewege, Gebäude, Armeen, Wellen, Wirtschaft, Helden, Items, Boss und Aufträge. + +Verwende eine feste Simulationsschrittweite, explizite Zufallsquellen mit Seed und nachvollziehbare Ereignis-IDs. Prüfung und Visualisierung konsumieren denselben maßgeblichen Zustand. Fordere keine plattformübergreifende Bit-Identität durch gewöhnliche Physik oder Navigationssysteme, ohne sie tatsächlich nachzuweisen. + +Bots verwenden dieselben Befehle, Kosten, Sichtinformationen und Phasenregeln wie Menschen. Teststrategien umfassen Verteidigung, Lane-Druck, Heldeninvestition, Teamunterstützung und Bossfokus. Kein allwissender Bot, der noch unveröffentlichte gegnerische Planungsbefehle ausliest. + +Plane von Anfang an eine autoritative Matchinstanz; offline läuft sie lokal. Im Netzwerk validiert Host/Server Befehle und berechnet Besitz, Gold, Kampf und Sieg. Clients senden Absichten, nicht selbst errechnete Treffer oder Ressourcenstände. + +Netzwerkmeilenstein: sechs Slots, Host/Join per Direktverbindung, Bots für freie Slots, synchronisierte Phasen und Zustandsabgleich. Prüfe fremde Einheiten-IDs, Doppelkauf, veraltete Befehle und mehrfach gesendete Pakete. Ein Disconnect darf nicht als Kernzerstörung gelten. Dokumentiere Reconnect, Botübernahme oder sauberen technischen Abbruch; keine angebliche Hostmigration ohne Implementierung. + +Nutze zunächst lokale Loopback-Tests. Öffne nicht automatisch Ports im Router oder in der Firewall. Öffentliches Matchmaking, Accounts, Ranglisten, Shop und Cloudinfrastruktur sind nicht Teil dieses ersten Umbaus. Ein Zwei-Prozess-Test ist als solcher zu benennen, nicht als verifizierte Internetpartie auf sechs Rechnern. + +## 13. Präsentation, Benutzerführung und Leistung + +Entwickle das neue Hauptmenü und gemeinsame Theme weiter. Benenne Spieleroberfläche, Titel und neue Pakete in Champions of Luneraria um; zerlege dafür nicht blind interne Assetpfade und UIDs. Migriere vorhandene Benutzereinstellungen kontrolliert oder biete einen dokumentierten Fallback. + +HUD: drei Lanezustände, beide Kerne, eigenes Gold/Einkommen, Wellennummer, Planung/Kampf, eigene Formation, gewählter Held mit Items, angekündigte Angriffschampions, Bossanspruch und Grottensperre. Eine Minimap ermöglicht Orientierung und Lanewechsel der Kamera. Auswahlkontext statt aller Detailfenster gleichzeitig. + +Keine verbleibenden Beschriftungen wie „20-Wellen-Expedition“, „letzte Welle“ oder „Sieg nach Welle 20“ im neuen Modus. Bewegung reduzieren, Tastaturbedienung, Lesbarkeit, Fenstergrößenwechsel und zuverlässige Eingabeabschirmung bleiben erhalten. UI-Klicks dürfen keine zusätzliche Weltaktion auslösen. + +Atmosphäre darf Einheiten nicht unsichtbar machen. Echte Spielmodelle für Porträts verwenden. Keine separate animierte 3D-Szene für jede Karte. Prüfe tatsächliche Szenen statt ausschließlich leerer Modellgalerien. + +Miss CPU-, GPU-Zeit, Draw Calls, aktive Einheiten, Speicher und Ladezeiten. Reduziere zuerst vermeidbare Arbeit, unbeschränkte Effekte, überflüssige Schatten und doppelt geladene Ressourcen. Kein pauschales Downgrade aller Modelle oder 4K-Texturen. Wiederholte Menü-/Partiewechsel dürfen keinen fortschreitenden Ressourcenverlust verursachen. + +Ziel sind flüssige Kämpfe bei repräsentativer Maximalbelegung. Jede Performanceaussage nennt Hardware, Renderer, Auflösung und Szenario; kein universelles 60-FPS-Versprechen aus einer leeren Szene. + +## 14. Ausführung in Meilensteinen + +M0 – Migration vorbereiten: Bestandsprüfung, Assetmatrix, gesicherter Ausgangsstand, Regeln und Architekturentscheidungen. Bestehende technische Tests als Baseline ausführen. Neue Tests und Legacyregeln klar trennen. + +M1 – Spielbarer Drei-Lane-Kern: sechs Rollen, ein Mensch/fünf Bots, vorrückende Armeen, Wellen, sechzehn Türme, zwei Kerne, persistenter Gebäudeschaden und Partieende ausschließlich durch Kernzerstörung. Vorhandene Modelle und ein bedienbares HUD verwenden. Einen vollständigen Sieg tatsächlich spielen oder reproduzierbar simulieren. + +M2 – Vollständiger Mechanikdurchlauf: Goldökonomie, mindestens drei verschiedene Angriffschampions, drei Heldentypen, sechs Items, normale Truppenaufwertungen und komplette Bossregel einschließlich Streitfall und Sperre. Alte Arbeiterökonomie darf nicht verdeckt weiterlaufen. + +M3 – Qualität und Balance: mehrere Seeds und Teamzusammensetzungen, Seitentausch, Gegenstrategien, hohe Wellenindizes, tatsächliche 3D-Karte und visuelle Überarbeitung. Dann fehlende Volksrepräsentanten ergänzen, ohne den Kern erneut umzubauen. + +M4 – Netzwerk und Pakete: autoritatives Host/Join für sechs Slots, reale Mehrprozessprüfungen, reproduzierbare Linux-/Windows-Exports, installier- beziehungsweise entpackbare Demo und klare Testmatrix. Öffentliches Matchmaking bleibt außerhalb des Umfangs. + +Arbeite M0 bis M4 nacheinander ab und gehe erst nach erfüllten Kriterien weiter. Liefere bereits nach M1 einen startfähigen Stand, setze danach den Auftrag fort. Wird die Sitzung begrenzt, dokumentiere den letzten grünen Meilenstein und den exakten nächsten Schritt; ersetze keinen fehlenden Meilenstein durch eine bloße Behauptung. + +## 15. Abnahme und Nachweise + +Automatisiert mindestens prüfen: + +1. Genau zwei Teams, sechs Eigentümerrollen, drei Lanes, sechzehn Türme und zwei Kerne. +2. Turmreihenfolge, Basisschutz und Sieg durch Kernzerstörung; gleichzeitige Kernzerstörung ohne Reihenfolgevorteil. +3. Fortsetzung nach Welle 20 sowie hohe Wellenindizes ohne Final-Wave-Logik, Fehler oder unbegrenztes Objektwachstum. +4. Goldbelohnung exakt einmal, gültige Besitzprüfung, keine Reset-/Despawn-/Beschwörungsfarmen. +5. Heilung und Persistenz nach einer Runde; neue Partie ohne übernommene Heldenwerte. +6. Normale Truppen ohne Heldeninventar; Heldentalente und drei Itemplätze mit korrektem Stapelverhalten. +7. Verstärkungskauf in n führt nur zum gebuchten Einsatz in n+1, auf der richtigen Lane und für das richtige Team. +8. Grottenabzug schwächt die Lane für die gesamte Kampfphase; kein früher Rücktransfer. +9. Beide Expeditionen, Scheitern, Erfolg, genau eine Entsendung, hohes Gegnerkopfgeld und Verfügbarkeit im Beispiel ab Runde 10. +10. Verhalten bei Laneverlust, Phasenende, Pause, Neustart und Rückkehr ins Menü. +11. Bots ohne Sonderressourcen und Sicht auf private Befehle. +12. Im Netzwerk doppelte/veraltete/fremde Befehle, synchroner Phasenwechsel, Disconnect und Zustandsabgleich. + +Alte Saumwacht-Kampfresultate müssen nach diesem ausdrücklich beauftragten Regelumbau nicht dieselben Kern-HP ergeben. Bewahre technische Regressionen, archiviere überholte Regeln nachvollziehbar und schreibe neue Referenzen erst nach fachlicher Prüfung. Keine willkürliche Erwartungswertanpassung, nur um grüne Tests zu erhalten. + +Balanceberichte zeigen Partiedauer, Wave beim Ende, Goldverläufe, Laneverluste, Helden-/Itemwirkung und Bossrisiko. Kleine Botstichproben beweisen keine ausgewogene Spielerfahrung. Endlose Testpartien sind ein zu untersuchendes Ergebnis, kein Anlass für einen versteckten Sieger-Timer. + +Visuelle Nachweise aus der echten Anwendung: Übersichtskarte, Kampf pro Lane, Held mit Items, Bosskampf, Bossentsendung, Kernzerstörung und Ergebnis. Zeige mindestens eine zusammenhängende Aufnahme echter Bedienung. Keine Konzeptillustration als Laufzeit-Screenshot ausgeben. + +Fedora 44 und Windows 11 separat bewerten. Ein exportiertes Windows-Paket, eine Prüfung seiner Dateien unter Linux oder ein Wine-Lauf ist kein nativer Windows-11-Test. Fehlende Hardware transparent kennzeichnen und ein ausführbares Testprotokoll bereitstellen. Keine Tests erfinden. + +## 16. Dokumentation und Abschluss + +Lege projektgerecht einen gemeinsamen Dokumentationsbereich an, beispielsweise docs/luneraria/, mit: +- verbindlichem Regelwerk und getrennten Arbeitsannahmen, +- Architektur-/Migrationsentscheidungen, +- Asset-Wiederverwendungsmatrix, +- Balancekonfiguration und Auswertungen, +- QA-Matrix und belegten Testläufen, +- Installations-, Start-, Steuerungs- und Exportanleitung, +- STATUS.md mit abgeschlossen, offen, blockiert und nächstem Schritt. + +Halte bestehende Projektanweisungen konsistent, ohne fremde CLAUDE.md-Inhalte pauschal zu überschreiben. Benenne Paketversionen nachvollziehbar, bewahre alte Saumwacht-Releases und liste wirklich erzeugte Pfade auf. Quellen, persönliche Dateien und Entwicklungslogs gehören nicht versehentlich ins Spielerpaket. + +Fasse zum Abschluss zusammen: tatsächlich implementierte Mechaniken, wiederverwendete und neu erstellte Assets, ausgeführte Tests, Plattformabdeckung, bekannte Probleme und Startbefehle. Unterscheide konzipiert, implementiert und geprüft. + +Beginne jetzt mit M0 und anschließend unmittelbar mit der Implementierung von M1. Entwickle kein weiteres bloßes Konzept. Entwickle das bestehende Spiel kontrolliert zu Champions of Luneraria weiter. diff --git a/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-1.png b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-1.png new file mode 100644 index 0000000..fff3325 Binary files /dev/null and b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-1.png differ diff --git a/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-2.png b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-2.png new file mode 100644 index 0000000..d9d0bb0 Binary files /dev/null and b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_52-2.png differ diff --git a/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_53-3.png b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_53-3.png new file mode 100644 index 0000000..8731e3f Binary files /dev/null and b/assets/ChatGPT-Bild 27. Sept. 2026, 19_46_53-3.png differ diff --git a/assets/audio/ability.wav b/assets/audio/ability.wav new file mode 100644 index 0000000..c0dfa2b Binary files /dev/null and b/assets/audio/ability.wav differ diff --git a/assets/audio/ability.wav.import b/assets/audio/ability.wav.import new file mode 100644 index 0000000..e0e2c73 --- /dev/null +++ b/assets/audio/ability.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://bosl577bjgutc" +path="res://.godot/imported/ability.wav-fdd8832832dd83cdd92e8a0dd55d1de8.sample" + +[deps] + +source_file="res://assets/audio/ability.wav" +dest_files=["res://.godot/imported/ability.wav-fdd8832832dd83cdd92e8a0dd55d1de8.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/bolt.wav b/assets/audio/bolt.wav new file mode 100644 index 0000000..1a79923 Binary files /dev/null and b/assets/audio/bolt.wav differ diff --git a/assets/audio/bolt.wav.import b/assets/audio/bolt.wav.import new file mode 100644 index 0000000..57160c7 --- /dev/null +++ b/assets/audio/bolt.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://ck7ncmrxdml43" +path="res://.godot/imported/bolt.wav-ad1b977c34cac4f8325e5adde9b6be6f.sample" + +[deps] + +source_file="res://assets/audio/bolt.wav" +dest_files=["res://.godot/imported/bolt.wav-ad1b977c34cac4f8325e5adde9b6be6f.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/boss.wav b/assets/audio/boss.wav new file mode 100644 index 0000000..a1ebe18 Binary files /dev/null and b/assets/audio/boss.wav differ diff --git a/assets/audio/boss.wav.import b/assets/audio/boss.wav.import new file mode 100644 index 0000000..0e7ed51 --- /dev/null +++ b/assets/audio/boss.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://csub5tbmfe0gl" +path="res://.godot/imported/boss.wav-ddb6c7f6bdafc090efb2210b84ae8009.sample" + +[deps] + +source_file="res://assets/audio/boss.wav" +dest_files=["res://.godot/imported/boss.wav-ddb6c7f6bdafc090efb2210b84ae8009.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/defeat.wav b/assets/audio/defeat.wav new file mode 100644 index 0000000..32c467e Binary files /dev/null and b/assets/audio/defeat.wav differ diff --git a/assets/audio/defeat.wav.import b/assets/audio/defeat.wav.import new file mode 100644 index 0000000..dc54aeb --- /dev/null +++ b/assets/audio/defeat.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://u0vg7ik35o0s" +path="res://.godot/imported/defeat.wav-2c373cdad262b5fb9203b05423989caa.sample" + +[deps] + +source_file="res://assets/audio/defeat.wav" +dest_files=["res://.godot/imported/defeat.wav-2c373cdad262b5fb9203b05423989caa.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/ember.wav b/assets/audio/ember.wav new file mode 100644 index 0000000..0170672 Binary files /dev/null and b/assets/audio/ember.wav differ diff --git a/assets/audio/ember.wav.import b/assets/audio/ember.wav.import new file mode 100644 index 0000000..14dfe8d --- /dev/null +++ b/assets/audio/ember.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://dfg4mjf2spl31" +path="res://.godot/imported/ember.wav-e8b1143e388c1a0a725ec4ff0632a78c.sample" + +[deps] + +source_file="res://assets/audio/ember.wav" +dest_files=["res://.godot/imported/ember.wav-e8b1143e388c1a0a725ec4ff0632a78c.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/error.wav b/assets/audio/error.wav new file mode 100644 index 0000000..5dd0483 Binary files /dev/null and b/assets/audio/error.wav differ diff --git a/assets/audio/error.wav.import b/assets/audio/error.wav.import new file mode 100644 index 0000000..8118048 --- /dev/null +++ b/assets/audio/error.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://bl0bpfeamj5w3" +path="res://.godot/imported/error.wav-99844ed22afbc0c517ece11da3662cae.sample" + +[deps] + +source_file="res://assets/audio/error.wav" +dest_files=["res://.godot/imported/error.wav-99844ed22afbc0c517ece11da3662cae.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/leak.wav b/assets/audio/leak.wav new file mode 100644 index 0000000..f65597f Binary files /dev/null and b/assets/audio/leak.wav differ diff --git a/assets/audio/leak.wav.import b/assets/audio/leak.wav.import new file mode 100644 index 0000000..2719be3 --- /dev/null +++ b/assets/audio/leak.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://b4ka7ekt0t20v" +path="res://.godot/imported/leak.wav-c611621a568fab156cc0849d961ea789.sample" + +[deps] + +source_file="res://assets/audio/leak.wav" +dest_files=["res://.godot/imported/leak.wav-c611621a568fab156cc0849d961ea789.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/manifest.json b/assets/audio/manifest.json new file mode 100644 index 0000000..89fd20c --- /dev/null +++ b/assets/audio/manifest.json @@ -0,0 +1,83 @@ +{ + "origin": "Original procedural synthesis; tools/generate_audio.py", + "clips": [ + { + "id": "place", + "seconds": 0.22, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "error", + "seconds": 0.2, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "stone", + "seconds": 0.24, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "bolt", + "seconds": 0.22, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "mortar", + "seconds": 0.5, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "ember", + "seconds": 0.24, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "ability", + "seconds": 0.65, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "wave", + "seconds": 0.9, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "boss", + "seconds": 1.25, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "settle", + "seconds": 0.65, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "leak", + "seconds": 0.55, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "victory", + "seconds": 1.8, + "peak": 0.55, + "sample_rate": 24000 + }, + { + "id": "defeat", + "seconds": 1.4, + "peak": 0.55, + "sample_rate": 24000 + } + ] +} diff --git a/assets/audio/mortar.wav b/assets/audio/mortar.wav new file mode 100644 index 0000000..abe93a1 Binary files /dev/null and b/assets/audio/mortar.wav differ diff --git a/assets/audio/mortar.wav.import b/assets/audio/mortar.wav.import new file mode 100644 index 0000000..d605c5a --- /dev/null +++ b/assets/audio/mortar.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://2ehedtm88imj" +path="res://.godot/imported/mortar.wav-222f237854a5d3823497ebaedddcae13.sample" + +[deps] + +source_file="res://assets/audio/mortar.wav" +dest_files=["res://.godot/imported/mortar.wav-222f237854a5d3823497ebaedddcae13.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/place.wav b/assets/audio/place.wav new file mode 100644 index 0000000..258b953 Binary files /dev/null and b/assets/audio/place.wav differ diff --git a/assets/audio/place.wav.import b/assets/audio/place.wav.import new file mode 100644 index 0000000..458229f --- /dev/null +++ b/assets/audio/place.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cjfrs0wo08obr" +path="res://.godot/imported/place.wav-1edabb5558d5fd30aa083ae98cd39bf2.sample" + +[deps] + +source_file="res://assets/audio/place.wav" +dest_files=["res://.godot/imported/place.wav-1edabb5558d5fd30aa083ae98cd39bf2.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/settle.wav b/assets/audio/settle.wav new file mode 100644 index 0000000..cf19e77 Binary files /dev/null and b/assets/audio/settle.wav differ diff --git a/assets/audio/settle.wav.import b/assets/audio/settle.wav.import new file mode 100644 index 0000000..7fa2bf0 --- /dev/null +++ b/assets/audio/settle.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://b5qkojaukxhdq" +path="res://.godot/imported/settle.wav-faeddf3df676658684c459ba0583f125.sample" + +[deps] + +source_file="res://assets/audio/settle.wav" +dest_files=["res://.godot/imported/settle.wav-faeddf3df676658684c459ba0583f125.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/stone.wav b/assets/audio/stone.wav new file mode 100644 index 0000000..27d1562 Binary files /dev/null and b/assets/audio/stone.wav differ diff --git a/assets/audio/stone.wav.import b/assets/audio/stone.wav.import new file mode 100644 index 0000000..dd71f60 --- /dev/null +++ b/assets/audio/stone.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://p2goxieb0h7n" +path="res://.godot/imported/stone.wav-a11f61dfccb0b90ec21960f1f0119a16.sample" + +[deps] + +source_file="res://assets/audio/stone.wav" +dest_files=["res://.godot/imported/stone.wav-a11f61dfccb0b90ec21960f1f0119a16.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/victory.wav b/assets/audio/victory.wav new file mode 100644 index 0000000..cf9d8c3 Binary files /dev/null and b/assets/audio/victory.wav differ diff --git a/assets/audio/victory.wav.import b/assets/audio/victory.wav.import new file mode 100644 index 0000000..1fedaa3 --- /dev/null +++ b/assets/audio/victory.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://ds8k8u350msve" +path="res://.godot/imported/victory.wav-d893d32ad919f27e15cf04d35e288b78.sample" + +[deps] + +source_file="res://assets/audio/victory.wav" +dest_files=["res://.godot/imported/victory.wav-d893d32ad919f27e15cf04d35e288b78.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/audio/wave.wav b/assets/audio/wave.wav new file mode 100644 index 0000000..9932537 Binary files /dev/null and b/assets/audio/wave.wav differ diff --git a/assets/audio/wave.wav.import b/assets/audio/wave.wav.import new file mode 100644 index 0000000..4f50113 --- /dev/null +++ b/assets/audio/wave.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cvy6t35cpccpd" +path="res://.godot/imported/wave.wav-ae74c5513bc05b360486f7d0e7fcb597.sample" + +[deps] + +source_file="res://assets/audio/wave.wav" +dest_files=["res://.godot/imported/wave.wav-ae74c5513bc05b360486f7d0e7fcb597.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=2 diff --git a/assets/characters/arbeiter.glb b/assets/characters/arbeiter.glb new file mode 100644 index 0000000..e241638 Binary files /dev/null and b/assets/characters/arbeiter.glb differ diff --git a/assets/characters/arbeiter.glb.import b/assets/characters/arbeiter.glb.import new file mode 100644 index 0000000..065110e --- /dev/null +++ b/assets/characters/arbeiter.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://biphx064q4usn" +path="res://.godot/imported/arbeiter.glb-2047438764904e2463e8dedeb3025be5.scn" + +[deps] + +source_file="res://assets/characters/arbeiter.glb" +dest_files=["res://.godot/imported/arbeiter.glb-2047438764904e2463e8dedeb3025be5.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/basaltbastion.glb b/assets/characters/basaltbastion.glb new file mode 100644 index 0000000..b2c33e5 Binary files /dev/null and b/assets/characters/basaltbastion.glb differ diff --git a/assets/characters/basaltbastion.glb.import b/assets/characters/basaltbastion.glb.import new file mode 100644 index 0000000..f6a609f --- /dev/null +++ b/assets/characters/basaltbastion.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://doxsnwamyhj8j" +path="res://.godot/imported/basaltbastion.glb-e655de904960d652a92c1784f2d7d071.scn" + +[deps] + +source_file="res://assets/characters/basaltbastion.glb" +dest_files=["res://.godot/imported/basaltbastion.glb-e655de904960d652a92c1784f2d7d071.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/funkenlanze.glb b/assets/characters/funkenlanze.glb new file mode 100644 index 0000000..5f81ad4 Binary files /dev/null and b/assets/characters/funkenlanze.glb differ diff --git a/assets/characters/funkenlanze.glb.import b/assets/characters/funkenlanze.glb.import new file mode 100644 index 0000000..7ca9ba6 --- /dev/null +++ b/assets/characters/funkenlanze.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://scewum8xmaiy" +path="res://.godot/imported/funkenlanze.glb-f093a0b3467ca9c94f3adbf610fca3ab.scn" + +[deps] + +source_file="res://assets/characters/funkenlanze.glb" +dest_files=["res://.godot/imported/funkenlanze.glb-f093a0b3467ca9c94f3adbf610fca3ab.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/glasballiste.glb b/assets/characters/glasballiste.glb new file mode 100644 index 0000000..3066fc3 Binary files /dev/null and b/assets/characters/glasballiste.glb differ diff --git a/assets/characters/glasballiste.glb.import b/assets/characters/glasballiste.glb.import new file mode 100644 index 0000000..566f1d5 --- /dev/null +++ b/assets/characters/glasballiste.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bh0aqueaskctf" +path="res://.godot/imported/glasballiste.glb-45514a548eee4570369d71c535130ba6.scn" + +[deps] + +source_file="res://assets/characters/glasballiste.glb" +dest_files=["res://.godot/imported/glasballiste.glb-45514a548eee4570369d71c535130ba6.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/quellgeflecht.glb b/assets/characters/quellgeflecht.glb new file mode 100644 index 0000000..7d8b51b Binary files /dev/null and b/assets/characters/quellgeflecht.glb differ diff --git a/assets/characters/quellgeflecht.glb.import b/assets/characters/quellgeflecht.glb.import new file mode 100644 index 0000000..dbdcc1d --- /dev/null +++ b/assets/characters/quellgeflecht.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ssyv03pq7ird" +path="res://.godot/imported/quellgeflecht.glb-de438fe7a2bd47d05d14a691f729fdf9.scn" + +[deps] + +source_file="res://assets/characters/quellgeflecht.glb" +dest_files=["res://.godot/imported/quellgeflecht.glb-de438fe7a2bd47d05d14a691f729fdf9.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/ringborke.glb b/assets/characters/ringborke.glb new file mode 100644 index 0000000..88d5d22 Binary files /dev/null and b/assets/characters/ringborke.glb differ diff --git a/assets/characters/ringborke.glb.import b/assets/characters/ringborke.glb.import new file mode 100644 index 0000000..64c6b2e --- /dev/null +++ b/assets/characters/ringborke.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bt15wixy17326" +path="res://.godot/imported/ringborke.glb-737d8a9106e0b6665a414c551a74d2c3.scn" + +[deps] + +source_file="res://assets/characters/ringborke.glb" +dest_files=["res://.godot/imported/ringborke.glb-737d8a9106e0b6665a414c551a74d2c3.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/characters/ringborke_oak-height-4k.png b/assets/characters/ringborke_oak-height-4k.png new file mode 100644 index 0000000..5107549 Binary files /dev/null and b/assets/characters/ringborke_oak-height-4k.png differ diff --git a/assets/characters/ringborke_oak-height-4k.png.import b/assets/characters/ringborke_oak-height-4k.png.import new file mode 100644 index 0000000..dc766d2 --- /dev/null +++ b/assets/characters/ringborke_oak-height-4k.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://qglgrg8yrddc" +path.bptc="res://.godot/imported/ringborke_oak-height-4k.png-cfd49dae7a34a547b10e0dd2f64aea40.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "e81293d81332a8c06af327c6c321b362" +} + +[deps] + +source_file="res://assets/characters/ringborke_oak-height-4k.png" +dest_files=["res://.godot/imported/ringborke_oak-height-4k.png-cfd49dae7a34a547b10e0dd2f64aea40.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/characters/ringborke_ringborke-cut-albedo-4k.png b/assets/characters/ringborke_ringborke-cut-albedo-4k.png new file mode 100644 index 0000000..658be47 Binary files /dev/null and b/assets/characters/ringborke_ringborke-cut-albedo-4k.png differ diff --git a/assets/characters/ringborke_ringborke-cut-albedo-4k.png.import b/assets/characters/ringborke_ringborke-cut-albedo-4k.png.import new file mode 100644 index 0000000..7b2486e --- /dev/null +++ b/assets/characters/ringborke_ringborke-cut-albedo-4k.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://varymvp2etyi" +path.bptc="res://.godot/imported/ringborke_ringborke-cut-albedo-4k.png-73c85421d02040c31d6a8d7e1fd502e5.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "d1dd93bfd02e10a456050a42fd527343" +} + +[deps] + +source_file="res://assets/characters/ringborke_ringborke-cut-albedo-4k.png" +dest_files=["res://.godot/imported/ringborke_ringborke-cut-albedo-4k.png-73c85421d02040c31d6a8d7e1fd502e5.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/characters/ringborke_ringborke-cut-normal-4k.png b/assets/characters/ringborke_ringborke-cut-normal-4k.png new file mode 100644 index 0000000..098d49b Binary files /dev/null and b/assets/characters/ringborke_ringborke-cut-normal-4k.png differ diff --git a/assets/characters/ringborke_ringborke-cut-normal-4k.png.import b/assets/characters/ringborke_ringborke-cut-normal-4k.png.import new file mode 100644 index 0000000..3058d65 --- /dev/null +++ b/assets/characters/ringborke_ringborke-cut-normal-4k.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqy23d8gmsx38" +path.bptc="res://.godot/imported/ringborke_ringborke-cut-normal-4k.png-9bdfa6557e64b2117e348dcc9fc861c3.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "800b1a6533bd17cb5961b545bf44d758" +} + +[deps] + +source_file="res://assets/characters/ringborke_ringborke-cut-normal-4k.png" +dest_files=["res://.godot/imported/ringborke_ringborke-cut-normal-4k.png-9bdfa6557e64b2117e348dcc9fc861c3.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/characters/ringborke_ringborke-cut-roughness-4k.png b/assets/characters/ringborke_ringborke-cut-roughness-4k.png new file mode 100644 index 0000000..c8ebb26 Binary files /dev/null and b/assets/characters/ringborke_ringborke-cut-roughness-4k.png differ diff --git a/assets/characters/ringborke_ringborke-cut-roughness-4k.png.import b/assets/characters/ringborke_ringborke-cut-roughness-4k.png.import new file mode 100644 index 0000000..589cfdf --- /dev/null +++ b/assets/characters/ringborke_ringborke-cut-roughness-4k.png.import @@ -0,0 +1,44 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b1phtpe3asudy" +path.bptc="res://.godot/imported/ringborke_ringborke-cut-roughness-4k.png-d74b9087b174fb5af2fc65e3b578dce3.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} +generator_parameters={ +"md5": "c63f3f6efc0222b44c23b709f94461b3" +} + +[deps] + +source_file="res://assets/characters/ringborke_ringborke-cut-roughness-4k.png" +dest_files=["res://.godot/imported/ringborke_ringborke-cut-roughness-4k.png-d74b9087b174fb5af2fc65e3b578dce3.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/compare/arbeiter-compare.glb b/assets/compare/arbeiter-compare.glb new file mode 100644 index 0000000..e241638 Binary files /dev/null and b/assets/compare/arbeiter-compare.glb differ diff --git a/assets/compare/arbeiter-compare.glb.import b/assets/compare/arbeiter-compare.glb.import new file mode 100644 index 0000000..10bb490 --- /dev/null +++ b/assets/compare/arbeiter-compare.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ck5tmwvjnvi14" +path="res://.godot/imported/arbeiter-compare.glb-9f8ae875e97f3fff22a26da939904465.scn" + +[deps] + +source_file="res://assets/compare/arbeiter-compare.glb" +dest_files=["res://.godot/imported/arbeiter-compare.glb-9f8ae875e97f3fff22a26da939904465.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/compare-arena-tile.glb b/assets/compare/compare-arena-tile.glb new file mode 100644 index 0000000..559898f Binary files /dev/null and b/assets/compare/compare-arena-tile.glb differ diff --git a/assets/compare/compare-arena-tile.glb.import b/assets/compare/compare-arena-tile.glb.import new file mode 100644 index 0000000..328123b --- /dev/null +++ b/assets/compare/compare-arena-tile.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dsso71vin17s3" +path="res://.godot/imported/compare-arena-tile.glb-ff9b41eb5140440d8b354b1a77c6f431.scn" + +[deps] + +source_file="res://assets/compare/compare-arena-tile.glb" +dest_files=["res://.godot/imported/compare-arena-tile.glb-ff9b41eb5140440d8b354b1a77c6f431.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/compare-manifest.json b/assets/compare/compare-manifest.json new file mode 100644 index 0000000..6740ffa --- /dev/null +++ b/assets/compare/compare-manifest.json @@ -0,0 +1,134 @@ +{ + "scene": "godot_unreal_compare", + "camera": { + "projection": "orthogonal", + "game_size": 4.6, + "game_position": [ + 0.0, + 7.2, + 6.8 + ], + "game_look_at": [ + 0.0, + 0.5, + 0.0 + ], + "game_yaw": 0.2, + "close_size": 2.1, + "close_position": [ + 1.3, + 1.5, + 1.9 + ], + "close_look_at": [ + 0.0, + 0.9, + 0.15 + ] + }, + "lighting": { + "key": { + "rotation_degrees": [ + -40, + -30, + 0 + ], + "color": "#ffd4a0", + "energy": 1.55 + }, + "fill": { + "rotation_degrees": [ + -32, + 148, + 0 + ], + "color": "#a8c4e8", + "energy": 0.48 + }, + "ambient": "#a8b4c8", + "tonemap": "ACES" + }, + "assets": [ + { + "id": "compare_rock", + "role": "prop_rock", + "resource_path": "res://assets/compare/compare-rock.glb", + "triangles": 360, + "bounds_godot": { + "min": [ + -1.0129448175430298, + -0.760317325592041, + -1.350000023841858 + ], + "max": [ + 1.195098876953125, + 0.8693029284477234, + 0.1893923133611679 + ] + }, + "sha256": "6fe3b527975f227f9040782e24ea7c87693e038e8ad09cc2a5b50bf9221414a8", + "source": "assets-source/phase14/build_compare_props.py" + }, + { + "id": "compare_tree", + "role": "prop_tree", + "resource_path": "res://assets/compare/compare-tree.glb", + "triangles": 852, + "bounds_godot": { + "min": [ + -0.9815748333930969, + -1.0770471096038818, + -2.430000066757202 + ], + "max": [ + 1.071698784828186, + 1.0116279125213623, + -0.0 + ] + }, + "sha256": "80aa80d8bd71a1ed1837df4c43d80367dd4c7643e5e7ca41bee3e8e4ac35c533", + "source": "assets-source/phase14/build_compare_props.py" + }, + { + "id": "compare_arena_tile", + "role": "prop_arena", + "resource_path": "res://assets/compare/compare-arena-tile.glb", + "triangles": 12, + "bounds_godot": { + "min": [ + -2.0, + -2.0, + -0.0 + ], + "max": [ + 2.0, + 2.0, + 0.18000000715255737 + ] + }, + "sha256": "c172a34a6a67bf247323bb66fc0132c87602deb179e277e16160c4b793eca9ae", + "source": "assets-source/phase14/build_compare_props.py" + }, + { + "id": "compare_ringborke", + "role": "figure_pattern", + "resource_path": "res://assets/compare/ringborke-compare.glb", + "source_asset": "res://assets/characters/ringborke.glb", + "sha256": "a9c61bcb7ae957c3e6b035ef994db3c8736b7a5f89d62724162dd606b76895b8" + }, + { + "id": "compare_arbeiter", + "role": "figure_worker", + "resource_path": "res://assets/compare/arbeiter-compare.glb", + "source_asset": "res://assets/characters/arbeiter.glb", + "sha256": "6b61389e6806cf130376665bcf791c5948e070a49593702faebaafad52d7d6d2" + }, + { + "id": "compare_core", + "role": "prop_core", + "resource_path": "res://assets/compare/core_team0-compare.glb", + "source_asset": "res://assets/models/core_team0.glb", + "sha256": "81a5305fc55482e6ca19524b72787d585211643d8842840efb4bdaf844660181" + } + ] +} diff --git a/assets/compare/compare-rock.glb b/assets/compare/compare-rock.glb new file mode 100644 index 0000000..9537d5f Binary files /dev/null and b/assets/compare/compare-rock.glb differ diff --git a/assets/compare/compare-rock.glb.import b/assets/compare/compare-rock.glb.import new file mode 100644 index 0000000..012ae21 --- /dev/null +++ b/assets/compare/compare-rock.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bdjgh4dfs1u03" +path="res://.godot/imported/compare-rock.glb-52ac65f5633ffa10816590ba9bf810da.scn" + +[deps] + +source_file="res://assets/compare/compare-rock.glb" +dest_files=["res://.godot/imported/compare-rock.glb-52ac65f5633ffa10816590ba9bf810da.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/compare-tree.glb b/assets/compare/compare-tree.glb new file mode 100644 index 0000000..8b0c0fd Binary files /dev/null and b/assets/compare/compare-tree.glb differ diff --git a/assets/compare/compare-tree.glb.import b/assets/compare/compare-tree.glb.import new file mode 100644 index 0000000..490f6c7 --- /dev/null +++ b/assets/compare/compare-tree.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://um0gnshh5jfr" +path="res://.godot/imported/compare-tree.glb-b838ac2528711f17566678385a10c088.scn" + +[deps] + +source_file="res://assets/compare/compare-tree.glb" +dest_files=["res://.godot/imported/compare-tree.glb-b838ac2528711f17566678385a10c088.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/core_team0-compare.glb b/assets/compare/core_team0-compare.glb new file mode 100644 index 0000000..4f4b684 Binary files /dev/null and b/assets/compare/core_team0-compare.glb differ diff --git a/assets/compare/core_team0-compare.glb.import b/assets/compare/core_team0-compare.glb.import new file mode 100644 index 0000000..054f327 --- /dev/null +++ b/assets/compare/core_team0-compare.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cquhwoeb3hgpy" +path="res://.godot/imported/core_team0-compare.glb-c011195bbe6c102255fc525f7aac9dfd.scn" + +[deps] + +source_file="res://assets/compare/core_team0-compare.glb" +dest_files=["res://.godot/imported/core_team0-compare.glb-c011195bbe6c102255fc525f7aac9dfd.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/ringborke-compare.glb b/assets/compare/ringborke-compare.glb new file mode 100644 index 0000000..88d5d22 Binary files /dev/null and b/assets/compare/ringborke-compare.glb differ diff --git a/assets/compare/ringborke-compare.glb.import b/assets/compare/ringborke-compare.glb.import new file mode 100644 index 0000000..b751442 --- /dev/null +++ b/assets/compare/ringborke-compare.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dleauub2icock" +path="res://.godot/imported/ringborke-compare.glb-d1a509123c4fe825a01688d581ffa92e.scn" + +[deps] + +source_file="res://assets/compare/ringborke-compare.glb" +dest_files=["res://.godot/imported/ringborke-compare.glb-d1a509123c4fe825a01688d581ffa92e.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/compare/ringborke-compare_oak-height-4k.png b/assets/compare/ringborke-compare_oak-height-4k.png new file mode 100644 index 0000000..5107549 Binary files /dev/null and b/assets/compare/ringborke-compare_oak-height-4k.png differ diff --git a/assets/compare/ringborke-compare_oak-height-4k.png.import b/assets/compare/ringborke-compare_oak-height-4k.png.import new file mode 100644 index 0000000..8b0c7a5 --- /dev/null +++ b/assets/compare/ringborke-compare_oak-height-4k.png.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chl1ndxgkb75c" +path="res://.godot/imported/ringborke-compare_oak-height-4k.png-29a1e38d0b199b014c0b78b810ecd4d3.ctex" +metadata={ +"vram_texture": false +} +generator_parameters={ +"md5": "e81293d81332a8c06af327c6c321b362" +} + +[deps] + +source_file="res://assets/compare/ringborke-compare_oak-height-4k.png" +dest_files=["res://.godot/imported/ringborke-compare_oak-height-4k.png-29a1e38d0b199b014c0b78b810ecd4d3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png b/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png new file mode 100644 index 0000000..658be47 Binary files /dev/null and b/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png differ diff --git a/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png.import b/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png.import new file mode 100644 index 0000000..ae24bae --- /dev/null +++ b/assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dfd82bl83fwxk" +path="res://.godot/imported/ringborke-compare_ringborke-cut-albedo-4k.png-1c4c2de58288af3893a4a0967649da84.ctex" +metadata={ +"vram_texture": false +} +generator_parameters={ +"md5": "d1dd93bfd02e10a456050a42fd527343" +} + +[deps] + +source_file="res://assets/compare/ringborke-compare_ringborke-cut-albedo-4k.png" +dest_files=["res://.godot/imported/ringborke-compare_ringborke-cut-albedo-4k.png-1c4c2de58288af3893a4a0967649da84.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png b/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png new file mode 100644 index 0000000..098d49b Binary files /dev/null and b/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png differ diff --git a/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png.import b/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png.import new file mode 100644 index 0000000..548e7e6 --- /dev/null +++ b/assets/compare/ringborke-compare_ringborke-cut-normal-4k.png.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d0h1kuuw4gw6d" +path="res://.godot/imported/ringborke-compare_ringborke-cut-normal-4k.png-42c3c8dd8fb100f41ffb35978757edef.ctex" +metadata={ +"vram_texture": false +} +generator_parameters={ +"md5": "800b1a6533bd17cb5961b545bf44d758" +} + +[deps] + +source_file="res://assets/compare/ringborke-compare_ringborke-cut-normal-4k.png" +dest_files=["res://.godot/imported/ringborke-compare_ringborke-cut-normal-4k.png-42c3c8dd8fb100f41ffb35978757edef.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png b/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png new file mode 100644 index 0000000..c8ebb26 Binary files /dev/null and b/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png differ diff --git a/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png.import b/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png.import new file mode 100644 index 0000000..c253c0c --- /dev/null +++ b/assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bhshwyxp124b5" +path="res://.godot/imported/ringborke-compare_ringborke-cut-roughness-4k.png-5e347505d4c9e74b86658b3042ddec4e.ctex" +metadata={ +"vram_texture": false +} +generator_parameters={ +"md5": "c63f3f6efc0222b44c23b709f94461b3" +} + +[deps] + +source_file="res://assets/compare/ringborke-compare_ringborke-cut-roughness-4k.png" +dest_files=["res://.godot/imported/ringborke-compare_ringborke-cut-roughness-4k.png-5e347505d4c9e74b86658b3042ddec4e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/concepts/map_lane_edge.png b/assets/concepts/map_lane_edge.png new file mode 100644 index 0000000..fb951f9 Binary files /dev/null and b/assets/concepts/map_lane_edge.png differ diff --git a/assets/concepts/map_lane_edge.png.import b/assets/concepts/map_lane_edge.png.import new file mode 100644 index 0000000..2088ab6 --- /dev/null +++ b/assets/concepts/map_lane_edge.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bq4oe80gu3u17" +path="res://.godot/imported/map_lane_edge.png-4c746da9cad616b1fb5ac9d0229d9314.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/concepts/map_lane_edge.png" +dest_files=["res://.godot/imported/map_lane_edge.png-4c746da9cad616b1fb5ac9d0229d9314.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/concepts/map_lane_floor.png b/assets/concepts/map_lane_floor.png new file mode 100644 index 0000000..d4a3ead Binary files /dev/null and b/assets/concepts/map_lane_floor.png differ diff --git a/assets/concepts/map_lane_floor.png.import b/assets/concepts/map_lane_floor.png.import new file mode 100644 index 0000000..704aa47 --- /dev/null +++ b/assets/concepts/map_lane_floor.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chf5o2qwhpf27" +path="res://.godot/imported/map_lane_floor.png-2b096a20027b2a014731dcb74048ea2e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/concepts/map_lane_floor.png" +dest_files=["res://.godot/imported/map_lane_floor.png-2b096a20027b2a014731dcb74048ea2e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/concepts/map_leak_line.png b/assets/concepts/map_leak_line.png new file mode 100644 index 0000000..6442a2b Binary files /dev/null and b/assets/concepts/map_leak_line.png differ diff --git a/assets/concepts/map_leak_line.png.import b/assets/concepts/map_leak_line.png.import new file mode 100644 index 0000000..ced64e6 --- /dev/null +++ b/assets/concepts/map_leak_line.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cymxkvk1ykwia" +path="res://.godot/imported/map_leak_line.png-46bfc1a22a04a9163fe15638ab741f05.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/concepts/map_leak_line.png" +dest_files=["res://.godot/imported/map_leak_line.png-46bfc1a22a04a9163fe15638ab741f05.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/concepts/map_overview.png b/assets/concepts/map_overview.png new file mode 100644 index 0000000..37bfaf2 Binary files /dev/null and b/assets/concepts/map_overview.png differ diff --git a/assets/concepts/map_overview.png.import b/assets/concepts/map_overview.png.import new file mode 100644 index 0000000..dd1afc2 --- /dev/null +++ b/assets/concepts/map_overview.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d2dnx6ml0pxc4" +path="res://.godot/imported/map_overview.png-07d3694e71c461d773a4b2aa4ac4d668.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/concepts/map_overview.png" +dest_files=["res://.godot/imported/map_overview.png-07d3694e71c461d773a4b2aa4ac4d668.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/environment/menu-stage.glb b/assets/environment/menu-stage.glb new file mode 100644 index 0000000..8b969f8 Binary files /dev/null and b/assets/environment/menu-stage.glb differ diff --git a/assets/environment/menu-stage.glb.import b/assets/environment/menu-stage.glb.import new file mode 100644 index 0000000..4c38b62 --- /dev/null +++ b/assets/environment/menu-stage.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ce108uhvr5deg" +path="res://.godot/imported/menu-stage.glb-448cd8dbf8156884ce282260035a08fa.scn" + +[deps] + +source_file="res://assets/environment/menu-stage.glb" +dest_files=["res://.godot/imported/menu-stage.glb-448cd8dbf8156884ce282260035a08fa.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/environment/verdant-rift.glb b/assets/environment/verdant-rift.glb new file mode 100644 index 0000000..02bbd13 Binary files /dev/null and b/assets/environment/verdant-rift.glb differ diff --git a/assets/environment/verdant-rift.glb.import b/assets/environment/verdant-rift.glb.import new file mode 100644 index 0000000..d9ab394 --- /dev/null +++ b/assets/environment/verdant-rift.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c8sihkvvo1hnc" +path="res://.godot/imported/verdant-rift.glb-1e5ee27e9df3a6f93d2e3c539b9b7a4a.scn" + +[deps] + +source_file="res://assets/environment/verdant-rift.glb" +dest_files=["res://.godot/imported/verdant-rift.glb-1e5ee27e9df3a6f93d2e3c539b9b7a4a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/fonts/Alegreya-Italic-VF.ttf b/assets/fonts/Alegreya-Italic-VF.ttf new file mode 100644 index 0000000..890f8f1 Binary files /dev/null and b/assets/fonts/Alegreya-Italic-VF.ttf differ diff --git a/assets/fonts/Alegreya-Italic-VF.ttf.import b/assets/fonts/Alegreya-Italic-VF.ttf.import new file mode 100644 index 0000000..8123c9d --- /dev/null +++ b/assets/fonts/Alegreya-Italic-VF.ttf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://coygdwoke7thf" +path="res://.godot/imported/Alegreya-Italic-VF.ttf-f45e57af2cca34e20ca2713500ef1e50.fontdata" + +[deps] + +source_file="res://assets/fonts/Alegreya-Italic-VF.ttf" +dest_files=["res://.godot/imported/Alegreya-Italic-VF.ttf-f45e57af2cca34e20ca2713500ef1e50.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/fonts/Alegreya-VF.ttf b/assets/fonts/Alegreya-VF.ttf new file mode 100644 index 0000000..af2b220 Binary files /dev/null and b/assets/fonts/Alegreya-VF.ttf differ diff --git a/assets/fonts/Alegreya-VF.ttf.import b/assets/fonts/Alegreya-VF.ttf.import new file mode 100644 index 0000000..3e0e2b4 --- /dev/null +++ b/assets/fonts/Alegreya-VF.ttf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://bypncyamonolq" +path="res://.godot/imported/Alegreya-VF.ttf-6e38efef7c148fb3799b72535ca2c51c.fontdata" + +[deps] + +source_file="res://assets/fonts/Alegreya-VF.ttf" +dest_files=["res://.godot/imported/Alegreya-VF.ttf-6e38efef7c148fb3799b72535ca2c51c.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/fonts/Cantarell-VF.otf b/assets/fonts/Cantarell-VF.otf new file mode 100644 index 0000000..960526d Binary files /dev/null and b/assets/fonts/Cantarell-VF.otf differ diff --git a/assets/fonts/Cantarell-VF.otf.import b/assets/fonts/Cantarell-VF.otf.import new file mode 100644 index 0000000..f427086 --- /dev/null +++ b/assets/fonts/Cantarell-VF.otf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://clkgxlvbionib" +path="res://.godot/imported/Cantarell-VF.otf-c2cabb826f2e2d715f6b23e3df84418a.fontdata" + +[deps] + +source_file="res://assets/fonts/Cantarell-VF.otf" +dest_files=["res://.godot/imported/Cantarell-VF.otf-c2cabb826f2e2d715f6b23e3df84418a.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/fonts/Cinzel-VF.ttf b/assets/fonts/Cinzel-VF.ttf new file mode 100644 index 0000000..d218a0b Binary files /dev/null and b/assets/fonts/Cinzel-VF.ttf differ diff --git a/assets/fonts/Cinzel-VF.ttf.import b/assets/fonts/Cinzel-VF.ttf.import new file mode 100644 index 0000000..821bd45 --- /dev/null +++ b/assets/fonts/Cinzel-VF.ttf.import @@ -0,0 +1,36 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://cklyygjsqocst" +path="res://.godot/imported/Cinzel-VF.ttf-686f60d84d215ded9ba0feee5a8abc8a.fontdata" + +[deps] + +source_file="res://assets/fonts/Cinzel-VF.ttf" +dest_files=["res://.godot/imported/Cinzel-VF.ttf-686f60d84d215ded9ba0feee5a8abc8a.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +modulate_color_glyphs=false +hinting=3 +subpixel_positioning=4 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/assets/fonts/OFL-Alegreya.txt b/assets/fonts/OFL-Alegreya.txt new file mode 100644 index 0000000..1a25b6d --- /dev/null +++ b/assets/fonts/OFL-Alegreya.txt @@ -0,0 +1,93 @@ +Copyright 2011 The Alegreya Project Authors (https://github.com/huertatipografica/Alegreya) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/fonts/OFL-Cantarell.txt b/assets/fonts/OFL-Cantarell.txt new file mode 100644 index 0000000..d9765dc --- /dev/null +++ b/assets/fonts/OFL-Cantarell.txt @@ -0,0 +1,111 @@ +Copyright (c) 2009--2019, The Cantarell Authors + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +------------------------------------------------------------------------------- + +Scripts contain parts of the source code of glyphsLib: + +# Copyright 2015 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/assets/fonts/OFL-Cinzel.txt b/assets/fonts/OFL-Cinzel.txt new file mode 100644 index 0000000..afdfd14 --- /dev/null +++ b/assets/fonts/OFL-Cinzel.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Cinzel Project Authors (https://github.com/NDISCOVER/Cinzel) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png b/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png new file mode 100644 index 0000000..b0f85bb Binary files /dev/null and b/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png differ diff --git a/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png.import b/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png.import new file mode 100644 index 0000000..e2d0a0b --- /dev/null +++ b/assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmydpk7n2g8lf" +path="res://.godot/imported/unit_g01_kohlenbeisser_icon.png-4bd0d0ddff33c30f24885631c11eb474.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png" +dest_files=["res://.godot/imported/unit_g01_kohlenbeisser_icon.png-4bd0d0ddff33c30f24885631c11eb474.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png b/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png new file mode 100644 index 0000000..69f3bc1 Binary files /dev/null and b/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png differ diff --git a/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png.import b/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png.import new file mode 100644 index 0000000..bdb35c1 --- /dev/null +++ b/assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cim863h354mat" +path="res://.godot/imported/unit_g02_schlackenklaue_icon.png-064080fee3735d12c903802db2e8389f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png" +dest_files=["res://.godot/imported/unit_g02_schlackenklaue_icon.png-064080fee3735d12c903802db2e8389f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png b/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png new file mode 100644 index 0000000..a41e00e Binary files /dev/null and b/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png differ diff --git a/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png.import b/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png.import new file mode 100644 index 0000000..15aeccd --- /dev/null +++ b/assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bcoxf0m5tmy08" +path="res://.godot/imported/unit_g03_schlackenwacht_icon.png-de9f5b10ebb0e019bafac7a9061794e7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png" +dest_files=["res://.godot/imported/unit_g03_schlackenwacht_icon.png-de9f5b10ebb0e019bafac7a9061794e7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png b/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png new file mode 100644 index 0000000..7dfee3d Binary files /dev/null and b/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png differ diff --git a/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png.import b/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png.import new file mode 100644 index 0000000..0a387c7 --- /dev/null +++ b/assets/icons/glutpakt/unit_g04_basaltbastion_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://du6vscs71rctu" +path="res://.godot/imported/unit_g04_basaltbastion_icon.png-54bda07564c771123621adcb1d252ac2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g04_basaltbastion_icon.png" +dest_files=["res://.godot/imported/unit_g04_basaltbastion_icon.png-54bda07564c771123621adcb1d252ac2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png b/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png new file mode 100644 index 0000000..e5d87e1 Binary files /dev/null and b/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png differ diff --git a/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png.import b/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png.import new file mode 100644 index 0000000..067801a --- /dev/null +++ b/assets/icons/glutpakt/unit_g05_funkenlanze_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://77b8ldv8y53f" +path="res://.godot/imported/unit_g05_funkenlanze_icon.png-b34f148bd54e16946e0c85a7dcf0cda1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g05_funkenlanze_icon.png" +dest_files=["res://.godot/imported/unit_g05_funkenlanze_icon.png-b34f148bd54e16946e0c85a7dcf0cda1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g06_glasballiste_icon.png b/assets/icons/glutpakt/unit_g06_glasballiste_icon.png new file mode 100644 index 0000000..7f4b3b4 Binary files /dev/null and b/assets/icons/glutpakt/unit_g06_glasballiste_icon.png differ diff --git a/assets/icons/glutpakt/unit_g06_glasballiste_icon.png.import b/assets/icons/glutpakt/unit_g06_glasballiste_icon.png.import new file mode 100644 index 0000000..c562751 --- /dev/null +++ b/assets/icons/glutpakt/unit_g06_glasballiste_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bv3e3ras67s55" +path="res://.godot/imported/unit_g06_glasballiste_icon.png-180e2a8c3862f98cc5a114527cb6f816.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g06_glasballiste_icon.png" +dest_files=["res://.godot/imported/unit_g06_glasballiste_icon.png-180e2a8c3862f98cc5a114527cb6f816.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png b/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png new file mode 100644 index 0000000..828595f Binary files /dev/null and b/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png differ diff --git a/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png.import b/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png.import new file mode 100644 index 0000000..73db37d --- /dev/null +++ b/assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bjw2ui3yrfjua" +path="res://.godot/imported/unit_g07_aschenwerfer_icon.png-34be9fec393ef2af92ee7826659392ee.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png" +dest_files=["res://.godot/imported/unit_g07_aschenwerfer_icon.png-34be9fec393ef2af92ee7826659392ee.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png b/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png new file mode 100644 index 0000000..7b5e73f Binary files /dev/null and b/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png differ diff --git a/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png.import b/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png.import new file mode 100644 index 0000000..2202a1b --- /dev/null +++ b/assets/icons/glutpakt/unit_g08_kraterrufer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c55mxxgqpr048" +path="res://.godot/imported/unit_g08_kraterrufer_icon.png-49d9bbeefb527abf28b7bd109daf37ce.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g08_kraterrufer_icon.png" +dest_files=["res://.godot/imported/unit_g08_kraterrufer_icon.png-49d9bbeefb527abf28b7bd109daf37ce.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g09_herdhueter_icon.png b/assets/icons/glutpakt/unit_g09_herdhueter_icon.png new file mode 100644 index 0000000..ac257a4 Binary files /dev/null and b/assets/icons/glutpakt/unit_g09_herdhueter_icon.png differ diff --git a/assets/icons/glutpakt/unit_g09_herdhueter_icon.png.import b/assets/icons/glutpakt/unit_g09_herdhueter_icon.png.import new file mode 100644 index 0000000..d222fac --- /dev/null +++ b/assets/icons/glutpakt/unit_g09_herdhueter_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://0mnp436tg83b" +path="res://.godot/imported/unit_g09_herdhueter_icon.png-b2482f709e8b91406686c5972529b6a1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g09_herdhueter_icon.png" +dest_files=["res://.godot/imported/unit_g09_herdhueter_icon.png-b2482f709e8b91406686c5972529b6a1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png b/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png new file mode 100644 index 0000000..4db8000 Binary files /dev/null and b/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png differ diff --git a/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png.import b/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png.import new file mode 100644 index 0000000..a5d4612 --- /dev/null +++ b/assets/icons/glutpakt/unit_g10_sonnenesse_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b0c5qpwd853d0" +path="res://.godot/imported/unit_g10_sonnenesse_icon.png-afa2a6c7312c28efc578740844db2c98.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/glutpakt/unit_g10_sonnenesse_icon.png" +dest_files=["res://.godot/imported/unit_g10_sonnenesse_icon.png-afa2a6c7312c28efc578740844db2c98.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/manifest.json b/assets/icons/manifest.json new file mode 100644 index 0000000..4b78e0b --- /dev/null +++ b/assets/icons/manifest.json @@ -0,0 +1,1237 @@ +{ + "phase": 3, + "assets": [ + { + "id": "g01", + "display_name": "Kohlenbeißer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter Basaltkörper mit glühendem Maul, kräftigen Klauen und Messingakzenten.", + "resource_path": "res://assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png", + "record_path": "assets-source/phase3/records/g01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "762bdd4aa646d58d7f1b2d1d39bb082d68b0d600955f73dfa839bd999554d97a", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g02", + "display_name": "Schlackenklaue", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwer gepanzerter Kohlenkörper mit breiten Basaltschultern, glühendem Maul und großen messingbesetzten Klauen.", + "resource_path": "res://assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png", + "record_path": "assets-source/phase3/records/g02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7c1ddff3a11e033ba0c105fcdb3a6a16a919b2aa30e4a56c0bf1be1b1e7ce1db", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g03", + "display_name": "Schlackenwacht", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Basaltwächter mit breiter Schildfront, schmaler Ofenglut und kurzen, kräftigen Armen.", + "resource_path": "res://assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png", + "record_path": "assets-source/phase3/records/g03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7f9d69bcd387551f69370bada56fa25f7ca00f4d00bcc5d144dea15635988708", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g04", + "display_name": "Basaltbastion", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Lebende Basaltfestung mit gestuften Schultern, gepanzerter Schildfront und glühendem Ofenkern.", + "resource_path": "res://assets/icons/glutpakt/unit_g04_basaltbastion_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png", + "record_path": "assets-source/phase3/records/g04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "2efa23fa99c3c85cf582bd0132e4db9fb454a8feedb81b4e6149e98ba999b1b9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g05", + "display_name": "Funkenlanze", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Glutkonstrukt-Schütze mit langer Messinglanze und orange leuchtender Glasspitze.", + "resource_path": "res://assets/icons/glutpakt/unit_g05_funkenlanze_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png", + "record_path": "assets-source/phase3/records/g05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c0883dc35abb007dcda5906a04ae29be995f4f80d4db7c1ab368de3b4addb519", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g06", + "display_name": "Glasballiste", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Bewegliche Glasballiste mit großen orangefarbenen Kristallarmen, langem Bolzen und stabilem Basaltunterbau.", + "resource_path": "res://assets/icons/glutpakt/unit_g06_glasballiste_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png", + "record_path": "assets-source/phase3/records/g06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c1eedabf95f65b662dd0ad5adda16b264bbb8121d23627cf6d9c0e646cf4669e", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g07", + "display_name": "Aschenwerfer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Aschenwerfer mit breitem Mörserkelch, glühender Kohle und kurzen Basaltbeinen.", + "resource_path": "res://assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png", + "record_path": "assets-source/phase3/records/g07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "38783c17d025f293fbe21086ee737eeb31fc5cb7152a4b24e066929e21684052", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g08", + "display_name": "Kraterrufer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwerer Kraterkörper mit großem Vulkankelch, glühendem Inneren und gestuften Basaltplatten.", + "resource_path": "res://assets/icons/glutpakt/unit_g08_kraterrufer_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png", + "record_path": "assets-source/phase3/records/g08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "141b2787c3fb0abdd3be30c628bbc5f767bf865a8576580194727b453f64c07c", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g09", + "display_name": "Herdhüter", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Herdwächter mit offenem Glutofen und einer schützenden Messingschale vor dem Körper.", + "resource_path": "res://assets/icons/glutpakt/unit_g09_herdhueter_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png", + "record_path": "assets-source/phase3/records/g09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b1acc547c67290c157b4ef7f3c1a842d98aaca2a289330111086b1a0ec5271b8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g10", + "display_name": "Sonnenesse", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Große Sonnenesse mit strahlender Ofenöffnung, Messingkrone und breiter wärmender Glutschale.", + "resource_path": "res://assets/icons/glutpakt/unit_g10_sonnenesse_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png", + "record_path": "assets-source/phase3/records/g10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "8be9406f7a64af3016549c55392a868952f28a03470ad7caa1ae21bda17029ed", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m01", + "display_name": "Kesselwicht", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Kesseltank mit rundem Petrolkessel, Keramikgesicht und kurzen Stempelbeinen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png", + "record_path": "assets-source/phase3/records/m01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "805516bc05c0071d8127ad9620d5e0259d849a5d2d5a77211fb3384621eb2431", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m02", + "display_name": "Druckhüter", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter gepanzerter Drucktank mit Schulterkesseln und massivem Schildarm.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png", + "record_path": "assets-source/phase3/records/m02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c807ed0a7f27c0ab97747e9fa1677e4a634d55f60917ec00712f149f394406dc", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m03", + "display_name": "Scherschreiter", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schmaler Schreitautomat mit zwei großen Scherenarmen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png", + "record_path": "assets-source/phase3/records/m03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "a787b97d68846d18b4e026737e68ee99f7c76dadd0049891fedd9ae71c29c791", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m04", + "display_name": "Sechsklingler", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Schreitautomat mit sechs deutlich getrennten Klingen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png", + "record_path": "assets-source/phase3/records/m04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "973e8288bc978d76e317a75710ee1d76f398286ba6c0c8dadf369601b64236ce", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m05", + "display_name": "Bolzenknecht", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Bolzenautomat mit einem deutlich lesbaren Armwerfer.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png", + "record_path": "assets-source/phase3/records/m05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "6e761bc1560e224b3f5960d956b95dae79d3edfd6a8a9c34aa9cb486d607e0ea", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m06", + "display_name": "Linienmeister", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Präzisionsautomat mit einer langen integrierten Balliste.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png", + "record_path": "assets-source/phase3/records/m06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "e20807102dc75df738b7d3b53dd49e2c9726895f53fbda5540f5b5fedb2164e2", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m07", + "display_name": "Klangkolben", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter Artillerieautomat mit einem großen Glockenrohr und Kolben.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png", + "record_path": "assets-source/phase3/records/m07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "91a12d9dfb9c7d7b2b32757443d5c6e591c974012a82002198de5f529694b180", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m08", + "display_name": "Resonanzramme", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Artillerieautomat mit zwei großen Resonanzkesseln.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png", + "record_path": "assets-source/phase3/records/m08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1e6966fd9f4d950abf2b8c841d2e9704b9685c38d99aecb7be16eb54f5848a57", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m09", + "display_name": "Taktspindel", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Taktgeber auf Spindelbeinen mit einem Dirigentenstab.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png", + "record_path": "assets-source/phase3/records/m09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "f4338c8a1e2625c2f607a9cf6663cfd590a9877afabce17d1c317356660b3109", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m10", + "display_name": "Taktprälat", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Uhrwerkdirigent mit kronenförmigem Metronom und breitem Mantelkörper.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png", + "record_path": "assets-source/phase3/records/m10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "5f11a0c174836e8a766b687bd962058caa4ec49979f59e1cafd9d28122c84302", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n01", + "display_name": "Saummaske", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter gefalteter Nebelkörper mit heller Ovalmaske, Sichelarmen und zwei Standranken.", + "resource_path": "res://assets/icons/nebelchor/unit_n01_saummaske_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png", + "record_path": "assets-source/phase3/records/n01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "38be12140e3bfe7cab181c9a1ecda37c797d0358b67f856a33119cc2d0645a3a", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n02", + "display_name": "Grenzmaske", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Nebeltank mit heller Ovalmaske und mehreren geschichteten Sichelschilden.", + "resource_path": "res://assets/icons/nebelchor/unit_n02_grenzmaske_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png", + "record_path": "assets-source/phase3/records/n02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "745ed920728e6450d307e3e1f6d4f8f9dd2a4aa758165cab8bce8f60de7a6ca8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n03", + "display_name": "Fadentänzer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker maskierter Nebeltänzer mit zwei versetzt geführten Fadenklingen und langen Standranken.", + "resource_path": "res://assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png", + "record_path": "assets-source/phase3/records/n03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "9d58b482e40ead9680778f4341ebc5153c645f42727618b83e9a6c188cbfbdd9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n04", + "display_name": "Saumzertrenner", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Nebelklingenkrieger mit Sichelkamm und großer geöffneter Sichelschere.", + "resource_path": "res://assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png", + "record_path": "assets-source/phase3/records/n04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "3a2c80cb65eab5849515e19b19821fef2ea1f685f3d5b5f7c97fce038dea1886", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n05", + "display_name": "Fernflüsterer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schmale gefaltete Maskenfigur mit langem Flüsterhorn und mintfarbener Schallöffnung.", + "resource_path": "res://assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png", + "record_path": "assets-source/phase3/records/n05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "ca2e0494ddf5ca1bfb2247f77dca44eb565dcad481ff147c6815fba3449e7878", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n06", + "display_name": "Fernrufer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Aufgewerteter Nebelrufer mit zwei weit geschwungenen Resonanzhörnern und mintfarbenen Schallöffnungen.", + "resource_path": "res://assets/icons/nebelchor/unit_n06_fernrufer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png", + "record_path": "assets-source/phase3/records/n06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "4db796780eccf39a417fc5096295c96c561ba8de0502651879cf62f83a51767f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n07", + "display_name": "Glockenschlepper", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Nebelträger mit großer heller Glocke und deutlich sichtbarem mintfarbenem Klöppel.", + "resource_path": "res://assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png", + "record_path": "assets-source/phase3/records/n07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d72a6247172ae48658e3f79b297a0e6b8eb2aed32c4fab317331595c9ff2c771", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n08", + "display_name": "Hohlgeläut", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher lebender Kathedralenglockenkörper mit drei Sichelspitzen und mintfarbenem Klöppel im offenen Brustraum.", + "resource_path": "res://assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png", + "record_path": "assets-source/phase3/records/n08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "43485c1f6b7f55ea5b5eee34692d503aa1b1df0c6c1f4ebfd902ce9f16f86f22", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n09", + "display_name": "Maskenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter maskierter Nebelsänger mit einer frei schwebenden Begleitmaske über dem erhobenen Sichelarm.", + "resource_path": "res://assets/icons/nebelchor/unit_n09_maskenkantor_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png", + "record_path": "assets-source/phase3/records/n09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "f6d5c42d7f7cee21d82ccc5d72b31a9e45c0eb3ee6742dcb2efcbb5bfae15798", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n10", + "display_name": "Vielstimmenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gekrönter Nebelchor-Kantor mit breitem Sichelkragen und drei getrennt schwebenden Begleitmasken.", + "resource_path": "res://assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png", + "record_path": "assets-source/phase3/records/n10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "18519abaa51aa463ebf4b7800d9c75742550d897fe30d77772cbb64f7860a0fd", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w01", + "display_name": "Dornhopser", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleine hüpfende Dornkapsel auf breiten Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w01_dornhopser_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png", + "record_path": "assets-source/phase3/records/w01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b20324131147bd27b0514f05fbbc9d763afb0bbc1185fe4578bc2f97ec3304a1", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w02", + "display_name": "Rankenschnapper", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Rankenräuber mit großem Dornenmaul und Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png", + "record_path": "assets-source/phase3/records/w02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b9cabce9916cf9821a93698b88b000d4dca25e9138eeca28385fdaaed4f357e4", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w03", + "display_name": "Korkrücken", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Tank mit breitem Korkpanzer, Moos und Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w03_korkruecken_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png", + "record_path": "assets-source/phase3/records/w03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "bf7ec6d9700c6b59d14953eb62aee48f6c2bb4d7180d9820ff75abb09e56e807", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w04", + "display_name": "Ringborke", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Wurzeltank mit konzentrischen Holzringen als massiver Panzerung.", + "resource_path": "res://assets/icons/wurzelbund/unit_w04_ringborke_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png", + "record_path": "assets-source/phase3/records/w04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b2681145788f69c0211444c022258c819e1eb268fb2f4ca27be39dacbbdf5151", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w05", + "display_name": "Samenschleuder", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Wurzelfernkämpfer mit gebogener Ranke und offener Samenkapsel als Wurfschale.", + "resource_path": "res://assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png", + "record_path": "assets-source/phase3/records/w05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "6b2b8da08701cea3172c9d9fb491ed8ef19d68b5e19969eca0ecdf4c198f5a9f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w06", + "display_name": "Zapfenkrone", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Samenschütze mit großer Zapfenkrone, kräftigen Ranken und Blattschalen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png", + "record_path": "assets-source/phase3/records/w06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7806055424d77d0cbf339e7ca7c316c597a5725553e01b1df163e54bb1bfe166", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w07", + "display_name": "Sporenkelch", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Niedriger offener Pilzkelch mit rosiger Sporenmulde und breiten Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png", + "record_path": "assets-source/phase3/records/w07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d696f2e7161c46c032c46913173be1e35747d729bb30ec931f891fe0a6f911ee", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w08", + "display_name": "Pilzkathedrale", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Große mobile Pilzarchitektur mit gestaffelten rosigen Pilzdächern und massivem Wurzelwerk.", + "resource_path": "res://assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png", + "record_path": "assets-source/phase3/records/w08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "5de336a54520876f5b9647fcf8158a42074a3c799be9fc554a79a50e6f806ce0", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w09", + "display_name": "Tauhüter", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Blatthüter mit einzelnem Tautropfen in einer schützenden Blattschale.", + "resource_path": "res://assets/icons/wurzelbund/unit_w09_tauhueter_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png", + "record_path": "assets-source/phase3/records/w09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b3fae10448ee3128e1e7d636ede427fd8477bb6080f67711e71aba5f467e2738", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w10", + "display_name": "Quellgeflecht", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Heiler aus verflochtenen Wurzeln mit Quellwasserschale unter einem Blüten- und Blätterdach.", + "resource_path": "res://assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png", + "record_path": "assets-source/phase3/records/w10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "69f386bf084e7d48d293195039d57c0284c3809fc5781b72e7b79af3beec2e93", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s01", + "display_name": "Nadelspäher", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker maskierter Söldnerspäher mit kompaktem Nadelwerfer.", + "resource_path": "res://assets/icons/neutral/unit_s01_nadelspaeher_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png", + "record_path": "assets-source/phase3/records/s01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "e90a5e0d9d651a4f4bd6ce95684bc4e7badb000abef719be69809f889c57ac03", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s02", + "display_name": "Rostschieber", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener schwerer Söldner mit Rostpanzer und großem Rammschild.", + "resource_path": "res://assets/icons/neutral/unit_s02_rostschieber_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png", + "record_path": "assets-source/phase3/records/s02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "295e2ee585816b0cfe3410aa2b5fcf92879d49cb4674d590cb0e50f2d861002d", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s03", + "display_name": "Dunstsänger", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Verhüllter violetter Dunstsänger mit großem Resonanzhorn.", + "resource_path": "res://assets/icons/neutral/unit_s03_dunstsaenger_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png", + "record_path": "assets-source/phase3/records/s03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "a3c0a2df180025d7e0afaab410c70d348f740feab1a45603ba9bf6a7fd8713c2", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s04", + "display_name": "Keilbrecher", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwerer dunkelgrauer Keilbrecher mit großem Keilhammer.", + "resource_path": "res://assets/icons/neutral/unit_s04_keilbrecher_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png", + "record_path": "assets-source/phase3/records/s04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "bd13a44d2f497a16eaabce31607cfbed9fa1f068bff2fa50e4643a95f6575b45", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s05", + "display_name": "Risszehrer", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hohler Risszehrer mit mintviolettem Schlund und magischer Entzugskugel.", + "resource_path": "res://assets/icons/neutral/unit_s05_risszehrer_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png", + "record_path": "assets-source/phase3/records/s05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c026f680dbf8c4979334bf05f475fc9e231247f6d68997a72d560133ed113bd9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_gold", + "display_name": "Gold", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Eine große facettierte Goldmünze mit zwei kleineren Münzen.", + "resource_path": "res://assets/icons/resources/res_gold.png", + "master_path": "assets-source/phase3/masters/resources/res_gold.png", + "record_path": "assets-source/phase3/records/res_gold.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c35163d614af2d20dd985ebcdd88c5a7aeb242a55f2b60fe0d3760dc8a175802", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_sparks", + "display_name": "Funken", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleines Messing-Glasgefäß mit leuchtender mintfarbener Funkenenergie.", + "resource_path": "res://assets/icons/resources/res_sparks.png", + "master_path": "assets-source/phase3/masters/resources/res_sparks.png", + "record_path": "assets-source/phase3/records/res_sparks.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d6a8a3d6518837d81455b4e64c67543112d0cb545479780d8af4827ad6f59b68", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_income", + "display_name": "Einkommen", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Messingsiegel mit drei von links nach rechts ansteigenden Münzstapeln.", + "resource_path": "res://assets/icons/resources/res_income.png", + "master_path": "assets-source/phase3/masters/resources/res_income.png", + "record_path": "assets-source/phase3/records/res_income.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "34877b2ffbd402273329137beaaa145e540ee9a06b94593b827f402de52bf163", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_core", + "display_name": "Kernleben", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Korallfarbenes facettiertes Kristallherz in einer kleinen Messingfassung.", + "resource_path": "res://assets/icons/resources/res_core.png", + "master_path": "assets-source/phase3/masters/resources/res_core.png", + "record_path": "assets-source/phase3/records/res_core.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b545deb38c922e26ef3b99bd976fa69d5622723c3847d2bd474d40162f4aa931", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "worker_funkenleser", + "display_name": "Funkenleser", + "faction": "neutral", + "kind": "worker_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleine Lehmgestalt im Arbeitstuch mit gegabeltem Funkensammler und Glasbehälter.", + "resource_path": "res://assets/icons/neutral/worker_funkenleser_icon.png", + "master_path": "assets-source/phase3/masters/neutral/worker_funkenleser_icon.png", + "record_path": "assets-source/phase3/records/worker_funkenleser.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "af4de34df59225e3d5f6a2f167227303978a3ccf4cac2208d74962013b517d12", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_blade", + "display_name": "Klinge", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Einzelne gebogene Elfenbeinklinge mit Messingparierstange und Graphitgriff.", + "resource_path": "res://assets/icons/types/type_damage_blade.png", + "master_path": "assets-source/phase3/masters/types/type_damage_blade.png", + "record_path": "assets-source/phase3/records/type_damage_blade.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d8166abd9bd9e8e68ef26debcf710c6e601d7d5afc73be27f5f09283892c867f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_pierce", + "display_name": "Durchschlag", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Lange Messingpfeilspitze durchstößt eine kleine graphitfarbene Rautenplatte.", + "resource_path": "res://assets/icons/types/type_damage_pierce.png", + "master_path": "assets-source/phase3/masters/types/type_damage_pierce.png", + "record_path": "assets-source/phase3/records/type_damage_pierce.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1d2d9b55d5da3be849194485e212a585393c7d69fa3a690dff1297e89b9884c0", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_pulse", + "display_name": "Impuls", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Mintfarbener facettierter Sternkern zwischen zwei offenen graphitfarbenen Ringhälften.", + "resource_path": "res://assets/icons/types/type_damage_pulse.png", + "master_path": "assets-source/phase3/masters/types/type_damage_pulse.png", + "record_path": "assets-source/phase3/records/type_damage_pulse.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "9d0c1807fcd16f3e01e53d33fd76f53f5815aa81e1aba9c43c8fe03e708541db", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_light", + "display_name": "Leichte Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Dünne blattförmige Lederpanzerplatte in warmem Ocker mit einfachem Graphitriemen.", + "resource_path": "res://assets/icons/types/type_armor_light.png", + "master_path": "assets-source/phase3/masters/types/type_armor_light.png", + "record_path": "assets-source/phase3/records/type_armor_light.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1a1bf7bb9ad703270ccd30fa4ea3e72f3f9139ff65198922183d8f5278f59d36", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_heavy", + "display_name": "Schwere Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breite schwere Schildplatte aus drei Graphitstahllagen mit hellen Kanten und Messingverstärkung.", + "resource_path": "res://assets/icons/types/type_armor_heavy.png", + "master_path": "assets-source/phase3/masters/types/type_armor_heavy.png", + "record_path": "assets-source/phase3/records/type_armor_heavy.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "ff1c430ec625abe969ae10b874cf8ee0c23ace39a881d84d336e1b6fb234a9c8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_aether", + "display_name": "Ätherische Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hohler violetter Geisterschild mit mintfarbener Innenkante und transparentem Innenraum.", + "resource_path": "res://assets/icons/types/type_armor_aether.png", + "master_path": "assets-source/phase3/masters/types/type_armor_aether.png", + "record_path": "assets-source/phase3/records/type_armor_aether.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7f9ffc611e252007a468e472bb9c9e4a2d95ba928624d54e1b0e5868174a9d4b", + "generation_mode": "built-in", + "status": "prepared" + } + ] +} diff --git a/assets/icons/nebelchor/unit_n01_saummaske_icon.png b/assets/icons/nebelchor/unit_n01_saummaske_icon.png new file mode 100644 index 0000000..9459b3b Binary files /dev/null and b/assets/icons/nebelchor/unit_n01_saummaske_icon.png differ diff --git a/assets/icons/nebelchor/unit_n01_saummaske_icon.png.import b/assets/icons/nebelchor/unit_n01_saummaske_icon.png.import new file mode 100644 index 0000000..e3513c1 --- /dev/null +++ b/assets/icons/nebelchor/unit_n01_saummaske_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://daisoqkqvrxeh" +path="res://.godot/imported/unit_n01_saummaske_icon.png-885e6d7300074d7e8a1e5a20c4469e26.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n01_saummaske_icon.png" +dest_files=["res://.godot/imported/unit_n01_saummaske_icon.png-885e6d7300074d7e8a1e5a20c4469e26.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png b/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png new file mode 100644 index 0000000..6de38b7 Binary files /dev/null and b/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png differ diff --git a/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png.import b/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png.import new file mode 100644 index 0000000..ec45f95 --- /dev/null +++ b/assets/icons/nebelchor/unit_n02_grenzmaske_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b04jyoiucb507" +path="res://.godot/imported/unit_n02_grenzmaske_icon.png-919ecbf2dd5e86294d297d6c167bf50f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n02_grenzmaske_icon.png" +dest_files=["res://.godot/imported/unit_n02_grenzmaske_icon.png-919ecbf2dd5e86294d297d6c167bf50f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png b/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png new file mode 100644 index 0000000..be168bf Binary files /dev/null and b/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png differ diff --git a/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png.import b/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png.import new file mode 100644 index 0000000..c893800 --- /dev/null +++ b/assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cj4nojo40yid3" +path="res://.godot/imported/unit_n03_fadentaenzer_icon.png-b5cdddfdf716991df2f81a6dec5eb246.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png" +dest_files=["res://.godot/imported/unit_n03_fadentaenzer_icon.png-b5cdddfdf716991df2f81a6dec5eb246.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png b/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png new file mode 100644 index 0000000..293f052 Binary files /dev/null and b/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png differ diff --git a/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png.import b/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png.import new file mode 100644 index 0000000..c894e6f --- /dev/null +++ b/assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dbutwjvqs02r5" +path="res://.godot/imported/unit_n04_saumzertrenner_icon.png-7db2acc34e7db95e81162c8428f0fb8e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png" +dest_files=["res://.godot/imported/unit_n04_saumzertrenner_icon.png-7db2acc34e7db95e81162c8428f0fb8e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png b/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png new file mode 100644 index 0000000..060ff44 Binary files /dev/null and b/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png differ diff --git a/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png.import b/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png.import new file mode 100644 index 0000000..edb831d --- /dev/null +++ b/assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bgeiy8lk65wb8" +path="res://.godot/imported/unit_n05_fernfluesterer_icon.png-4ae313c45938a9e183c45d3636350663.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png" +dest_files=["res://.godot/imported/unit_n05_fernfluesterer_icon.png-4ae313c45938a9e183c45d3636350663.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n06_fernrufer_icon.png b/assets/icons/nebelchor/unit_n06_fernrufer_icon.png new file mode 100644 index 0000000..3abcbf8 Binary files /dev/null and b/assets/icons/nebelchor/unit_n06_fernrufer_icon.png differ diff --git a/assets/icons/nebelchor/unit_n06_fernrufer_icon.png.import b/assets/icons/nebelchor/unit_n06_fernrufer_icon.png.import new file mode 100644 index 0000000..170fc8d --- /dev/null +++ b/assets/icons/nebelchor/unit_n06_fernrufer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cpqg0xagrxvlg" +path="res://.godot/imported/unit_n06_fernrufer_icon.png-dbc73972a00337f2a1883510c5676b3d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n06_fernrufer_icon.png" +dest_files=["res://.godot/imported/unit_n06_fernrufer_icon.png-dbc73972a00337f2a1883510c5676b3d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png b/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png new file mode 100644 index 0000000..be3b233 Binary files /dev/null and b/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png differ diff --git a/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png.import b/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png.import new file mode 100644 index 0000000..8907410 --- /dev/null +++ b/assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://clkk8wwmti6ns" +path="res://.godot/imported/unit_n07_glockenschlepper_icon.png-213c448876eff4eda3443aea18e78209.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png" +dest_files=["res://.godot/imported/unit_n07_glockenschlepper_icon.png-213c448876eff4eda3443aea18e78209.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png b/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png new file mode 100644 index 0000000..cb1ea81 Binary files /dev/null and b/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png differ diff --git a/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png.import b/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png.import new file mode 100644 index 0000000..d4bd8dc --- /dev/null +++ b/assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://deeyvrnx2bygm" +path="res://.godot/imported/unit_n08_hohlgelaeut_icon.png-eed80ded44fdb96b3791ad75b281a0c2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png" +dest_files=["res://.godot/imported/unit_n08_hohlgelaeut_icon.png-eed80ded44fdb96b3791ad75b281a0c2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png b/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png new file mode 100644 index 0000000..0e00b3e Binary files /dev/null and b/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png differ diff --git a/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png.import b/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png.import new file mode 100644 index 0000000..8713ff3 --- /dev/null +++ b/assets/icons/nebelchor/unit_n09_maskenkantor_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://djyjqbowt373e" +path="res://.godot/imported/unit_n09_maskenkantor_icon.png-e7c93002fa1eee38a27d2c3abb1ea736.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n09_maskenkantor_icon.png" +dest_files=["res://.godot/imported/unit_n09_maskenkantor_icon.png-e7c93002fa1eee38a27d2c3abb1ea736.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png b/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png new file mode 100644 index 0000000..64fb66f Binary files /dev/null and b/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png differ diff --git a/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png.import b/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png.import new file mode 100644 index 0000000..956e658 --- /dev/null +++ b/assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://hnfgg1ysc5ou" +path="res://.godot/imported/unit_n10_vielstimmenkantor_icon.png-ab6f5634b88e118ebb950608df4f74c1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png" +dest_files=["res://.godot/imported/unit_n10_vielstimmenkantor_icon.png-ab6f5634b88e118ebb950608df4f74c1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/unit_s01_nadelspaeher_icon.png b/assets/icons/neutral/unit_s01_nadelspaeher_icon.png new file mode 100644 index 0000000..b8c8357 Binary files /dev/null and b/assets/icons/neutral/unit_s01_nadelspaeher_icon.png differ diff --git a/assets/icons/neutral/unit_s01_nadelspaeher_icon.png.import b/assets/icons/neutral/unit_s01_nadelspaeher_icon.png.import new file mode 100644 index 0000000..756c83f --- /dev/null +++ b/assets/icons/neutral/unit_s01_nadelspaeher_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bfqld8chhal0d" +path="res://.godot/imported/unit_s01_nadelspaeher_icon.png-947fb3b21332b14682a7d9cdd1025fa7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/unit_s01_nadelspaeher_icon.png" +dest_files=["res://.godot/imported/unit_s01_nadelspaeher_icon.png-947fb3b21332b14682a7d9cdd1025fa7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/unit_s02_rostschieber_icon.png b/assets/icons/neutral/unit_s02_rostschieber_icon.png new file mode 100644 index 0000000..adc8041 Binary files /dev/null and b/assets/icons/neutral/unit_s02_rostschieber_icon.png differ diff --git a/assets/icons/neutral/unit_s02_rostschieber_icon.png.import b/assets/icons/neutral/unit_s02_rostschieber_icon.png.import new file mode 100644 index 0000000..62f6c27 --- /dev/null +++ b/assets/icons/neutral/unit_s02_rostschieber_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bra61oak3daek" +path="res://.godot/imported/unit_s02_rostschieber_icon.png-a0697802a03b14a367c4863723e882b3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/unit_s02_rostschieber_icon.png" +dest_files=["res://.godot/imported/unit_s02_rostschieber_icon.png-a0697802a03b14a367c4863723e882b3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/unit_s03_dunstsaenger_icon.png b/assets/icons/neutral/unit_s03_dunstsaenger_icon.png new file mode 100644 index 0000000..5e02cc4 Binary files /dev/null and b/assets/icons/neutral/unit_s03_dunstsaenger_icon.png differ diff --git a/assets/icons/neutral/unit_s03_dunstsaenger_icon.png.import b/assets/icons/neutral/unit_s03_dunstsaenger_icon.png.import new file mode 100644 index 0000000..7c6bd1a --- /dev/null +++ b/assets/icons/neutral/unit_s03_dunstsaenger_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dbf2wdvg14wfa" +path="res://.godot/imported/unit_s03_dunstsaenger_icon.png-d7ef874514bfa240a5a539754b998a39.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/unit_s03_dunstsaenger_icon.png" +dest_files=["res://.godot/imported/unit_s03_dunstsaenger_icon.png-d7ef874514bfa240a5a539754b998a39.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/unit_s04_keilbrecher_icon.png b/assets/icons/neutral/unit_s04_keilbrecher_icon.png new file mode 100644 index 0000000..91a98b2 Binary files /dev/null and b/assets/icons/neutral/unit_s04_keilbrecher_icon.png differ diff --git a/assets/icons/neutral/unit_s04_keilbrecher_icon.png.import b/assets/icons/neutral/unit_s04_keilbrecher_icon.png.import new file mode 100644 index 0000000..59f619e --- /dev/null +++ b/assets/icons/neutral/unit_s04_keilbrecher_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cdd8a7qyrvumn" +path="res://.godot/imported/unit_s04_keilbrecher_icon.png-8860c1fad0b749de51a2f52a07ab863e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/unit_s04_keilbrecher_icon.png" +dest_files=["res://.godot/imported/unit_s04_keilbrecher_icon.png-8860c1fad0b749de51a2f52a07ab863e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/unit_s05_risszehrer_icon.png b/assets/icons/neutral/unit_s05_risszehrer_icon.png new file mode 100644 index 0000000..77c1cd1 Binary files /dev/null and b/assets/icons/neutral/unit_s05_risszehrer_icon.png differ diff --git a/assets/icons/neutral/unit_s05_risszehrer_icon.png.import b/assets/icons/neutral/unit_s05_risszehrer_icon.png.import new file mode 100644 index 0000000..67d2e20 --- /dev/null +++ b/assets/icons/neutral/unit_s05_risszehrer_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqe42peklhegx" +path="res://.godot/imported/unit_s05_risszehrer_icon.png-f9285d44abe2c176ecdee4266618266e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/unit_s05_risszehrer_icon.png" +dest_files=["res://.godot/imported/unit_s05_risszehrer_icon.png-f9285d44abe2c176ecdee4266618266e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/neutral/worker_funkenleser_icon.png b/assets/icons/neutral/worker_funkenleser_icon.png new file mode 100644 index 0000000..c2e9bef Binary files /dev/null and b/assets/icons/neutral/worker_funkenleser_icon.png differ diff --git a/assets/icons/neutral/worker_funkenleser_icon.png.import b/assets/icons/neutral/worker_funkenleser_icon.png.import new file mode 100644 index 0000000..e6b437b --- /dev/null +++ b/assets/icons/neutral/worker_funkenleser_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://celv6mcwlw3lu" +path="res://.godot/imported/worker_funkenleser_icon.png-c885501db7219ccacb97097f62968c47.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/neutral/worker_funkenleser_icon.png" +dest_files=["res://.godot/imported/worker_funkenleser_icon.png-c885501db7219ccacb97097f62968c47.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png b/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png new file mode 100644 index 0000000..668ae1d Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png.import b/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png.import new file mode 100644 index 0000000..8e73feb --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://beao1rtpk1vuk" +path="res://.godot/imported/unit_m01_kesselwicht_icon.png-ce1b68e5a4e5fda32ab5a184244ae498.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png" +dest_files=["res://.godot/imported/unit_m01_kesselwicht_icon.png-ce1b68e5a4e5fda32ab5a184244ae498.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png b/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png new file mode 100644 index 0000000..8168dc1 Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png.import b/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png.import new file mode 100644 index 0000000..1574c8e --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cg3gv1w3dsq0d" +path="res://.godot/imported/unit_m02_druckhueter_icon.png-086bbd2e9da2f1bb7cb3f809ea535e7a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png" +dest_files=["res://.godot/imported/unit_m02_druckhueter_icon.png-086bbd2e9da2f1bb7cb3f809ea535e7a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png b/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png new file mode 100644 index 0000000..c46d585 Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png.import b/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png.import new file mode 100644 index 0000000..052d303 --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://deo3tolensuf2" +path="res://.godot/imported/unit_m03_scherschreiter_icon.png-22ae9e650c60676995a3b3c4607b6b53.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png" +dest_files=["res://.godot/imported/unit_m03_scherschreiter_icon.png-22ae9e650c60676995a3b3c4607b6b53.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png b/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png new file mode 100644 index 0000000..9e935c5 Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png.import b/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png.import new file mode 100644 index 0000000..0f29e83 --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://btkgnjukn5kbw" +path="res://.godot/imported/unit_m04_sechsklingler_icon.png-c6b7d230ee2c16ee502e38c0c1f36340.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png" +dest_files=["res://.godot/imported/unit_m04_sechsklingler_icon.png-c6b7d230ee2c16ee502e38c0c1f36340.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png b/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png new file mode 100644 index 0000000..8cb7217 Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png.import b/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png.import new file mode 100644 index 0000000..5777807 --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://clk3scrp34y3p" +path="res://.godot/imported/unit_m05_bolzenknecht_icon.png-47a2c9a70a72685036eecc1b914784bd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png" +dest_files=["res://.godot/imported/unit_m05_bolzenknecht_icon.png-47a2c9a70a72685036eecc1b914784bd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png b/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png new file mode 100644 index 0000000..538f76d Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png.import b/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png.import new file mode 100644 index 0000000..c8e1512 --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bykwuxr58t3e1" +path="res://.godot/imported/unit_m06_linienmeister_icon.png-55c3d19cfaa6acaeacbe11d3ced31c55.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png" +dest_files=["res://.godot/imported/unit_m06_linienmeister_icon.png-55c3d19cfaa6acaeacbe11d3ced31c55.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png b/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png new file mode 100644 index 0000000..8c6e080 Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png.import b/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png.import new file mode 100644 index 0000000..faa332c --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dlvd0t2mupku5" +path="res://.godot/imported/unit_m07_klangkolben_icon.png-1bc5809fd6a8bf35759d1207ac4bc8a0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png" +dest_files=["res://.godot/imported/unit_m07_klangkolben_icon.png-1bc5809fd6a8bf35759d1207ac4bc8a0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png b/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png new file mode 100644 index 0000000..87f639f Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png.import b/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png.import new file mode 100644 index 0000000..50bee1b --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b0ney0g3uth0t" +path="res://.godot/imported/unit_m08_resonanzramme_icon.png-bb76fce1deba4ef06a2da5ee337984d7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png" +dest_files=["res://.godot/imported/unit_m08_resonanzramme_icon.png-bb76fce1deba4ef06a2da5ee337984d7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png b/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png new file mode 100644 index 0000000..6e8fc4b Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png.import b/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png.import new file mode 100644 index 0000000..8aab05b --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://clx65556u6ap7" +path="res://.godot/imported/unit_m09_taktspindel_icon.png-430a980b8d4f074d94ca5a3df1140ce2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png" +dest_files=["res://.godot/imported/unit_m09_taktspindel_icon.png-430a980b8d4f074d94ca5a3df1140ce2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png b/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png new file mode 100644 index 0000000..bed770e Binary files /dev/null and b/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png differ diff --git a/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png.import b/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png.import new file mode 100644 index 0000000..e42a8fd --- /dev/null +++ b/assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cqm1hto2xjh33" +path="res://.godot/imported/unit_m10_taktpraelat_icon.png-88205b3c74cdaa86aac41d4731a2ebad.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png" +dest_files=["res://.godot/imported/unit_m10_taktpraelat_icon.png-88205b3c74cdaa86aac41d4731a2ebad.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/resources/res_core.png b/assets/icons/resources/res_core.png new file mode 100644 index 0000000..4cf62f3 Binary files /dev/null and b/assets/icons/resources/res_core.png differ diff --git a/assets/icons/resources/res_core.png.import b/assets/icons/resources/res_core.png.import new file mode 100644 index 0000000..d1f8093 --- /dev/null +++ b/assets/icons/resources/res_core.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bam5b27pnvoi8" +path="res://.godot/imported/res_core.png-82e5333d1b15f37452bfc093a8d9eaa4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/resources/res_core.png" +dest_files=["res://.godot/imported/res_core.png-82e5333d1b15f37452bfc093a8d9eaa4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/resources/res_gold.png b/assets/icons/resources/res_gold.png new file mode 100644 index 0000000..db6508a Binary files /dev/null and b/assets/icons/resources/res_gold.png differ diff --git a/assets/icons/resources/res_gold.png.import b/assets/icons/resources/res_gold.png.import new file mode 100644 index 0000000..3d66af9 --- /dev/null +++ b/assets/icons/resources/res_gold.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dt5w67tl21kma" +path="res://.godot/imported/res_gold.png-25d7242e041f0b427ffba2f1bbe0bb14.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/resources/res_gold.png" +dest_files=["res://.godot/imported/res_gold.png-25d7242e041f0b427ffba2f1bbe0bb14.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/resources/res_income.png b/assets/icons/resources/res_income.png new file mode 100644 index 0000000..64f29bd Binary files /dev/null and b/assets/icons/resources/res_income.png differ diff --git a/assets/icons/resources/res_income.png.import b/assets/icons/resources/res_income.png.import new file mode 100644 index 0000000..440a536 --- /dev/null +++ b/assets/icons/resources/res_income.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwdxodd6x7wgc" +path="res://.godot/imported/res_income.png-994cd3d4fd853fcf50b70b5cd9c18781.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/resources/res_income.png" +dest_files=["res://.godot/imported/res_income.png-994cd3d4fd853fcf50b70b5cd9c18781.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/resources/res_sparks.png b/assets/icons/resources/res_sparks.png new file mode 100644 index 0000000..5876c1a Binary files /dev/null and b/assets/icons/resources/res_sparks.png differ diff --git a/assets/icons/resources/res_sparks.png.import b/assets/icons/resources/res_sparks.png.import new file mode 100644 index 0000000..23eb639 --- /dev/null +++ b/assets/icons/resources/res_sparks.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cowqfesjrsvj0" +path="res://.godot/imported/res_sparks.png-04d87602cf4b9f9f800413638be1b98a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/resources/res_sparks.png" +dest_files=["res://.godot/imported/res_sparks.png-04d87602cf4b9f9f800413638be1b98a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_armor_aether.png b/assets/icons/types/type_armor_aether.png new file mode 100644 index 0000000..8b24732 Binary files /dev/null and b/assets/icons/types/type_armor_aether.png differ diff --git a/assets/icons/types/type_armor_aether.png.import b/assets/icons/types/type_armor_aether.png.import new file mode 100644 index 0000000..a9c1e7f --- /dev/null +++ b/assets/icons/types/type_armor_aether.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c13g2jaomlff8" +path="res://.godot/imported/type_armor_aether.png-5611313854f3f2cefe12ed73c6d671b4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_armor_aether.png" +dest_files=["res://.godot/imported/type_armor_aether.png-5611313854f3f2cefe12ed73c6d671b4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_armor_heavy.png b/assets/icons/types/type_armor_heavy.png new file mode 100644 index 0000000..fcc9438 Binary files /dev/null and b/assets/icons/types/type_armor_heavy.png differ diff --git a/assets/icons/types/type_armor_heavy.png.import b/assets/icons/types/type_armor_heavy.png.import new file mode 100644 index 0000000..f7f7dab --- /dev/null +++ b/assets/icons/types/type_armor_heavy.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://7uetkf5kx7lv" +path="res://.godot/imported/type_armor_heavy.png-c278c686f0cce3386fe3c4dbde130376.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_armor_heavy.png" +dest_files=["res://.godot/imported/type_armor_heavy.png-c278c686f0cce3386fe3c4dbde130376.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_armor_light.png b/assets/icons/types/type_armor_light.png new file mode 100644 index 0000000..1b69deb Binary files /dev/null and b/assets/icons/types/type_armor_light.png differ diff --git a/assets/icons/types/type_armor_light.png.import b/assets/icons/types/type_armor_light.png.import new file mode 100644 index 0000000..3689292 --- /dev/null +++ b/assets/icons/types/type_armor_light.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ym1pp6owfnuy" +path="res://.godot/imported/type_armor_light.png-5803a84fa4b99485d451e3e101dc9f9f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_armor_light.png" +dest_files=["res://.godot/imported/type_armor_light.png-5803a84fa4b99485d451e3e101dc9f9f.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_damage_blade.png b/assets/icons/types/type_damage_blade.png new file mode 100644 index 0000000..cfe6bdc Binary files /dev/null and b/assets/icons/types/type_damage_blade.png differ diff --git a/assets/icons/types/type_damage_blade.png.import b/assets/icons/types/type_damage_blade.png.import new file mode 100644 index 0000000..792234f --- /dev/null +++ b/assets/icons/types/type_damage_blade.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bhcy7imkj2rrh" +path="res://.godot/imported/type_damage_blade.png-b487b19cfcb2fc0f1c235279c5930a2a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_damage_blade.png" +dest_files=["res://.godot/imported/type_damage_blade.png-b487b19cfcb2fc0f1c235279c5930a2a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_damage_pierce.png b/assets/icons/types/type_damage_pierce.png new file mode 100644 index 0000000..670d053 Binary files /dev/null and b/assets/icons/types/type_damage_pierce.png differ diff --git a/assets/icons/types/type_damage_pierce.png.import b/assets/icons/types/type_damage_pierce.png.import new file mode 100644 index 0000000..cd4e035 --- /dev/null +++ b/assets/icons/types/type_damage_pierce.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cymmel3of508i" +path="res://.godot/imported/type_damage_pierce.png-eaeaf4f6d425dfe4f974dc7d504a6040.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_damage_pierce.png" +dest_files=["res://.godot/imported/type_damage_pierce.png-eaeaf4f6d425dfe4f974dc7d504a6040.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/types/type_damage_pulse.png b/assets/icons/types/type_damage_pulse.png new file mode 100644 index 0000000..63e38a4 Binary files /dev/null and b/assets/icons/types/type_damage_pulse.png differ diff --git a/assets/icons/types/type_damage_pulse.png.import b/assets/icons/types/type_damage_pulse.png.import new file mode 100644 index 0000000..da964ee --- /dev/null +++ b/assets/icons/types/type_damage_pulse.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b60aphn0olqwd" +path="res://.godot/imported/type_damage_pulse.png-7a45b12cf774c51695b978e85975d805.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/types/type_damage_pulse.png" +dest_files=["res://.godot/imported/type_damage_pulse.png-7a45b12cf774c51695b978e85975d805.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png b/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png new file mode 100644 index 0000000..8eea237 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png.import b/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png.import new file mode 100644 index 0000000..11008a2 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w01_dornhopser_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ls7vuqd70ai8" +path="res://.godot/imported/unit_w01_dornhopser_icon.png-4bfb0d07ab720a256d7e6a179c88862e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w01_dornhopser_icon.png" +dest_files=["res://.godot/imported/unit_w01_dornhopser_icon.png-4bfb0d07ab720a256d7e6a179c88862e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png b/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png new file mode 100644 index 0000000..9cbf36a Binary files /dev/null and b/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png.import b/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png.import new file mode 100644 index 0000000..5c33dd8 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://nswwwjwhgd1t" +path="res://.godot/imported/unit_w02_rankenschnapper_icon.png-cc3265a0332f95f15998765491d519ba.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png" +dest_files=["res://.godot/imported/unit_w02_rankenschnapper_icon.png-cc3265a0332f95f15998765491d519ba.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png b/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png new file mode 100644 index 0000000..647b0ee Binary files /dev/null and b/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png.import b/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png.import new file mode 100644 index 0000000..1a12685 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w03_korkruecken_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d0qe45uteipgl" +path="res://.godot/imported/unit_w03_korkruecken_icon.png-e14d513adf2a2ef0bb5e1c4d3cc67cac.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w03_korkruecken_icon.png" +dest_files=["res://.godot/imported/unit_w03_korkruecken_icon.png-e14d513adf2a2ef0bb5e1c4d3cc67cac.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w04_ringborke_icon.png b/assets/icons/wurzelbund/unit_w04_ringborke_icon.png new file mode 100644 index 0000000..59ac090 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w04_ringborke_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w04_ringborke_icon.png.import b/assets/icons/wurzelbund/unit_w04_ringborke_icon.png.import new file mode 100644 index 0000000..fd89e0e --- /dev/null +++ b/assets/icons/wurzelbund/unit_w04_ringborke_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chwtt3n0e8dnt" +path="res://.godot/imported/unit_w04_ringborke_icon.png-4ac23176977edf37b3414696816d8f54.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w04_ringborke_icon.png" +dest_files=["res://.godot/imported/unit_w04_ringborke_icon.png-4ac23176977edf37b3414696816d8f54.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png b/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png new file mode 100644 index 0000000..7a99188 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png.import b/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png.import new file mode 100644 index 0000000..59433e5 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cn3gk4w5dv5yu" +path="res://.godot/imported/unit_w05_samenschleuder_icon.png-f133d2e79d4d44c6378dc2ced0477f08.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png" +dest_files=["res://.godot/imported/unit_w05_samenschleuder_icon.png-f133d2e79d4d44c6378dc2ced0477f08.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png b/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png new file mode 100644 index 0000000..9f47670 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png.import b/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png.import new file mode 100644 index 0000000..5a5389a --- /dev/null +++ b/assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://455sh7yet7rj" +path="res://.godot/imported/unit_w06_zapfenkrone_icon.png-159d17054b0338bc342320667940396d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png" +dest_files=["res://.godot/imported/unit_w06_zapfenkrone_icon.png-159d17054b0338bc342320667940396d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png b/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png new file mode 100644 index 0000000..f3efa19 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png.import b/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png.import new file mode 100644 index 0000000..83e5be2 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bfwalcwgy1m0g" +path="res://.godot/imported/unit_w07_sporenkelch_icon.png-9d8cd5ade895a40e337c93bd4d3a8c89.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png" +dest_files=["res://.godot/imported/unit_w07_sporenkelch_icon.png-9d8cd5ade895a40e337c93bd4d3a8c89.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png b/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png new file mode 100644 index 0000000..6553736 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png.import b/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png.import new file mode 100644 index 0000000..246bc58 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://clbssneq8fpi7" +path="res://.godot/imported/unit_w08_pilzkathedrale_icon.png-d2cdb6b6668ed002e8b96e1961c6daa4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png" +dest_files=["res://.godot/imported/unit_w08_pilzkathedrale_icon.png-d2cdb6b6668ed002e8b96e1961c6daa4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png b/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png new file mode 100644 index 0000000..1668a25 Binary files /dev/null and b/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png.import b/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png.import new file mode 100644 index 0000000..24047e3 --- /dev/null +++ b/assets/icons/wurzelbund/unit_w09_tauhueter_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dre3t6gy2go8y" +path="res://.godot/imported/unit_w09_tauhueter_icon.png-b7e4d0316187fbd85020dce40c447d66.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w09_tauhueter_icon.png" +dest_files=["res://.godot/imported/unit_w09_tauhueter_icon.png-b7e4d0316187fbd85020dce40c447d66.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png b/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png new file mode 100644 index 0000000..99dafdc Binary files /dev/null and b/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png differ diff --git a/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png.import b/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png.import new file mode 100644 index 0000000..fe045eb --- /dev/null +++ b/assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c3xb3xckxhok0" +path="res://.godot/imported/unit_w10_quellgeflecht_icon.png-78abbef2fa5d8b761329cdcac9d06ff5.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png" +dest_files=["res://.godot/imported/unit_w10_quellgeflecht_icon.png-78abbef2fa5d8b761329cdcac9d06ff5.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=256 +detect_3d/compress_to=1 diff --git a/assets/materials/phase10/limestone-albedo.png b/assets/materials/phase10/limestone-albedo.png new file mode 100644 index 0000000..af6d1ee Binary files /dev/null and b/assets/materials/phase10/limestone-albedo.png differ diff --git a/assets/materials/phase10/limestone-albedo.png.import b/assets/materials/phase10/limestone-albedo.png.import new file mode 100644 index 0000000..40d026a --- /dev/null +++ b/assets/materials/phase10/limestone-albedo.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://gb8k2gh1fatp" +path.bptc="res://.godot/imported/limestone-albedo.png-e2ef74eda1463a024457e6fa83926f32.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/materials/phase10/limestone-albedo.png" +dest_files=["res://.godot/imported/limestone-albedo.png-e2ef74eda1463a024457e6fa83926f32.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/materials/phase10/oak-albedo-4k.png b/assets/materials/phase10/oak-albedo-4k.png new file mode 100644 index 0000000..cd15cae Binary files /dev/null and b/assets/materials/phase10/oak-albedo-4k.png differ diff --git a/assets/materials/phase10/oak-albedo-4k.png.import b/assets/materials/phase10/oak-albedo-4k.png.import new file mode 100644 index 0000000..b3809df --- /dev/null +++ b/assets/materials/phase10/oak-albedo-4k.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c5j13kmnfjj6q" +path.bptc="res://.godot/imported/oak-albedo-4k.png-9073c445a98157f52562d09fd5d5f9a7.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/materials/phase10/oak-albedo-4k.png" +dest_files=["res://.godot/imported/oak-albedo-4k.png-9073c445a98157f52562d09fd5d5f9a7.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/materials/phase10/oak-height-4k.png b/assets/materials/phase10/oak-height-4k.png new file mode 100644 index 0000000..5107549 Binary files /dev/null and b/assets/materials/phase10/oak-height-4k.png differ diff --git a/assets/materials/phase10/oak-height-4k.png.import b/assets/materials/phase10/oak-height-4k.png.import new file mode 100644 index 0000000..0dd9dc9 --- /dev/null +++ b/assets/materials/phase10/oak-height-4k.png.import @@ -0,0 +1,41 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dbx5xdwy7c2y1" +path.bptc="res://.godot/imported/oak-height-4k.png-178f6878e8a21b5c0ef060bf738f5274.bptc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/materials/phase10/oak-height-4k.png" +dest_files=["res://.godot/imported/oak-height-4k.png-178f6878e8a21b5c0ef060bf738f5274.bptc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=true +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/materials/phase11/ringborke-cut-albedo-4k.png b/assets/materials/phase11/ringborke-cut-albedo-4k.png new file mode 100644 index 0000000..658be47 Binary files /dev/null and b/assets/materials/phase11/ringborke-cut-albedo-4k.png differ diff --git a/assets/materials/phase11/ringborke-cut-albedo-4k.png.import b/assets/materials/phase11/ringborke-cut-albedo-4k.png.import new file mode 100644 index 0000000..218ac07 --- /dev/null +++ b/assets/materials/phase11/ringborke-cut-albedo-4k.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bcc74na5m6h0e" +path="res://.godot/imported/ringborke-cut-albedo-4k.png-bfcbb9b11235e1590c2a1ea2bf9742e8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/materials/phase11/ringborke-cut-albedo-4k.png" +dest_files=["res://.godot/imported/ringborke-cut-albedo-4k.png-bfcbb9b11235e1590c2a1ea2bf9742e8.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/materials/phase11/ringborke-cut-normal-4k.png b/assets/materials/phase11/ringborke-cut-normal-4k.png new file mode 100644 index 0000000..098d49b Binary files /dev/null and b/assets/materials/phase11/ringborke-cut-normal-4k.png differ diff --git a/assets/materials/phase11/ringborke-cut-normal-4k.png.import b/assets/materials/phase11/ringborke-cut-normal-4k.png.import new file mode 100644 index 0000000..eedd67b --- /dev/null +++ b/assets/materials/phase11/ringborke-cut-normal-4k.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bj3lvtbrr3fpp" +path="res://.godot/imported/ringborke-cut-normal-4k.png-86fc1a325351b00d77669108d63dbf76.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/materials/phase11/ringborke-cut-normal-4k.png" +dest_files=["res://.godot/imported/ringborke-cut-normal-4k.png-86fc1a325351b00d77669108d63dbf76.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/materials/phase11/ringborke-cut-roughness-4k.png b/assets/materials/phase11/ringborke-cut-roughness-4k.png new file mode 100644 index 0000000..17c8f86 Binary files /dev/null and b/assets/materials/phase11/ringborke-cut-roughness-4k.png differ diff --git a/assets/materials/phase11/ringborke-cut-roughness-4k.png.import b/assets/materials/phase11/ringborke-cut-roughness-4k.png.import new file mode 100644 index 0000000..f80d7c0 --- /dev/null +++ b/assets/materials/phase11/ringborke-cut-roughness-4k.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b83cshoqmuyxr" +path="res://.godot/imported/ringborke-cut-roughness-4k.png-20e97a9cd6282a113c13abc4fe5a7272.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/materials/phase11/ringborke-cut-roughness-4k.png" +dest_files=["res://.godot/imported/ringborke-cut-roughness-4k.png-20e97a9cd6282a113c13abc4fe5a7272.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/menu_stage_manifest.json b/assets/menu_stage_manifest.json new file mode 100644 index 0000000..cbc2e52 --- /dev/null +++ b/assets/menu_stage_manifest.json @@ -0,0 +1,64 @@ +{ + "resource_path": "res://assets/environment/menu-stage.glb", + "source": "assets-source/phase20/menu-stage.blend", + "triangles": 48660, + "sha256": "00584591fd11af912ba4d25b470d0bfc8a077744e833abcf25ca93c590ea6629", + "materials": [ + "ENV_cliff", + "ENV_soil", + "ENV_limestone", + "ENV_paving", + "ENV_teal", + "ENV_bark", + "ENV_leaf_dark", + "ENV_leaf_mid", + "ENV_leaf_light", + "ENV_spring", + "ENV_basalt", + "ENV_brass", + "ENV_ember" + ], + "daises": { + "wurzelbund": { + "center": [ + 4.0, + 0.37, + 0.3 + ], + "core": [ + 4.0, + 0.37, + -1.55 + ], + "spring": [ + 1.75, + 0.3, + -1.3 + ] + }, + "glutpakt": { + "center": [ + 3.0, + 1.28, + -10.6 + ], + "core": [ + 3.0, + 1.28, + -12.45 + ], + "braziers": [ + [ + 0.6499999999999999, + 2.18, + -9.049999999999999 + ], + [ + 5.35, + 2.18, + -9.049999999999999 + ] + ] + } + } +} diff --git a/assets/models/core_team0.glb b/assets/models/core_team0.glb new file mode 100644 index 0000000..4f4b684 Binary files /dev/null and b/assets/models/core_team0.glb differ diff --git a/assets/models/core_team0.glb.import b/assets/models/core_team0.glb.import new file mode 100644 index 0000000..3aeee4d --- /dev/null +++ b/assets/models/core_team0.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bxbms6fj5k6p2" +path="res://.godot/imported/core_team0.glb-dc914ed77f96790aa3502dcf7348579a.scn" + +[deps] + +source_file="res://assets/models/core_team0.glb" +dest_files=["res://.godot/imported/core_team0.glb-dc914ed77f96790aa3502dcf7348579a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/core_team1.glb b/assets/models/core_team1.glb new file mode 100644 index 0000000..fc11ded Binary files /dev/null and b/assets/models/core_team1.glb differ diff --git a/assets/models/core_team1.glb.import b/assets/models/core_team1.glb.import new file mode 100644 index 0000000..45bdeca --- /dev/null +++ b/assets/models/core_team1.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://b0hoilyl0lvco" +path="res://.godot/imported/core_team1.glb-b0c672e7710ace91311fc9032c1df658.scn" + +[deps] + +source_file="res://assets/models/core_team1.glb" +dest_files=["res://.godot/imported/core_team1.glb-b0c672e7710ace91311fc9032c1df658.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e01.glb b/assets/models/enemy_e01.glb new file mode 100644 index 0000000..875174e Binary files /dev/null and b/assets/models/enemy_e01.glb differ diff --git a/assets/models/enemy_e01.glb.import b/assets/models/enemy_e01.glb.import new file mode 100644 index 0000000..7c6f5f5 --- /dev/null +++ b/assets/models/enemy_e01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cetlfyev5plf7" +path="res://.godot/imported/enemy_e01.glb-1d01dbe7109090f3473b1f6d57a348ce.scn" + +[deps] + +source_file="res://assets/models/enemy_e01.glb" +dest_files=["res://.godot/imported/enemy_e01.glb-1d01dbe7109090f3473b1f6d57a348ce.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e02.glb b/assets/models/enemy_e02.glb new file mode 100644 index 0000000..2420caf Binary files /dev/null and b/assets/models/enemy_e02.glb differ diff --git a/assets/models/enemy_e02.glb.import b/assets/models/enemy_e02.glb.import new file mode 100644 index 0000000..7ff5e51 --- /dev/null +++ b/assets/models/enemy_e02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dchbadhihso0q" +path="res://.godot/imported/enemy_e02.glb-e20cd6ff699e524f8cbaa340c52ad308.scn" + +[deps] + +source_file="res://assets/models/enemy_e02.glb" +dest_files=["res://.godot/imported/enemy_e02.glb-e20cd6ff699e524f8cbaa340c52ad308.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e03.glb b/assets/models/enemy_e03.glb new file mode 100644 index 0000000..9737a49 Binary files /dev/null and b/assets/models/enemy_e03.glb differ diff --git a/assets/models/enemy_e03.glb.import b/assets/models/enemy_e03.glb.import new file mode 100644 index 0000000..4dce1b9 --- /dev/null +++ b/assets/models/enemy_e03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://b2ghiwrne0o83" +path="res://.godot/imported/enemy_e03.glb-94d588ddd758ff625f365b3c9f3ee42a.scn" + +[deps] + +source_file="res://assets/models/enemy_e03.glb" +dest_files=["res://.godot/imported/enemy_e03.glb-94d588ddd758ff625f365b3c9f3ee42a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e04.glb b/assets/models/enemy_e04.glb new file mode 100644 index 0000000..afe326c Binary files /dev/null and b/assets/models/enemy_e04.glb differ diff --git a/assets/models/enemy_e04.glb.import b/assets/models/enemy_e04.glb.import new file mode 100644 index 0000000..4f88b13 --- /dev/null +++ b/assets/models/enemy_e04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bwrm1fghrmd6" +path="res://.godot/imported/enemy_e04.glb-2e154842109f8657e505c5424f8ffbc1.scn" + +[deps] + +source_file="res://assets/models/enemy_e04.glb" +dest_files=["res://.godot/imported/enemy_e04.glb-2e154842109f8657e505c5424f8ffbc1.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e05.glb b/assets/models/enemy_e05.glb new file mode 100644 index 0000000..d8a2fb8 Binary files /dev/null and b/assets/models/enemy_e05.glb differ diff --git a/assets/models/enemy_e05.glb.import b/assets/models/enemy_e05.glb.import new file mode 100644 index 0000000..f7196c6 --- /dev/null +++ b/assets/models/enemy_e05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ctpdybocj0a1k" +path="res://.godot/imported/enemy_e05.glb-10e3a54b00c39bc44d9ba5827a357c1a.scn" + +[deps] + +source_file="res://assets/models/enemy_e05.glb" +dest_files=["res://.godot/imported/enemy_e05.glb-10e3a54b00c39bc44d9ba5827a357c1a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e06.glb b/assets/models/enemy_e06.glb new file mode 100644 index 0000000..45fcde5 Binary files /dev/null and b/assets/models/enemy_e06.glb differ diff --git a/assets/models/enemy_e06.glb.import b/assets/models/enemy_e06.glb.import new file mode 100644 index 0000000..d7a48a3 --- /dev/null +++ b/assets/models/enemy_e06.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c6po6fbpx8e67" +path="res://.godot/imported/enemy_e06.glb-5cc147341b5979a761ae1a616f8d0f4e.scn" + +[deps] + +source_file="res://assets/models/enemy_e06.glb" +dest_files=["res://.godot/imported/enemy_e06.glb-5cc147341b5979a761ae1a616f8d0f4e.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e07.glb b/assets/models/enemy_e07.glb new file mode 100644 index 0000000..b967802 Binary files /dev/null and b/assets/models/enemy_e07.glb differ diff --git a/assets/models/enemy_e07.glb.import b/assets/models/enemy_e07.glb.import new file mode 100644 index 0000000..1ee4197 --- /dev/null +++ b/assets/models/enemy_e07.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dxnsc7xp3hc47" +path="res://.godot/imported/enemy_e07.glb-271d3e919c3502fb1e3b4360341157f9.scn" + +[deps] + +source_file="res://assets/models/enemy_e07.glb" +dest_files=["res://.godot/imported/enemy_e07.glb-271d3e919c3502fb1e3b4360341157f9.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e08.glb b/assets/models/enemy_e08.glb new file mode 100644 index 0000000..cd3accb Binary files /dev/null and b/assets/models/enemy_e08.glb differ diff --git a/assets/models/enemy_e08.glb.import b/assets/models/enemy_e08.glb.import new file mode 100644 index 0000000..59f9985 --- /dev/null +++ b/assets/models/enemy_e08.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://db7vbe6qjolq7" +path="res://.godot/imported/enemy_e08.glb-13e8128ff52e5eb4813153c184794172.scn" + +[deps] + +source_file="res://assets/models/enemy_e08.glb" +dest_files=["res://.godot/imported/enemy_e08.glb-13e8128ff52e5eb4813153c184794172.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e09.glb b/assets/models/enemy_e09.glb new file mode 100644 index 0000000..586a265 Binary files /dev/null and b/assets/models/enemy_e09.glb differ diff --git a/assets/models/enemy_e09.glb.import b/assets/models/enemy_e09.glb.import new file mode 100644 index 0000000..a561bb1 --- /dev/null +++ b/assets/models/enemy_e09.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://d00iintyg4lpc" +path="res://.godot/imported/enemy_e09.glb-250185c80b609b1facc5ebcdabbfedb2.scn" + +[deps] + +source_file="res://assets/models/enemy_e09.glb" +dest_files=["res://.godot/imported/enemy_e09.glb-250185c80b609b1facc5ebcdabbfedb2.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/enemy_e10.glb b/assets/models/enemy_e10.glb new file mode 100644 index 0000000..d19c7c5 Binary files /dev/null and b/assets/models/enemy_e10.glb differ diff --git a/assets/models/enemy_e10.glb.import b/assets/models/enemy_e10.glb.import new file mode 100644 index 0000000..5301871 --- /dev/null +++ b/assets/models/enemy_e10.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dbtal8uau76ak" +path="res://.godot/imported/enemy_e10.glb-fd34b8f6e60675eab0422b4fc4458697.scn" + +[deps] + +source_file="res://assets/models/enemy_e10.glb" +dest_files=["res://.godot/imported/enemy_e10.glb-fd34b8f6e60675eab0422b4fc4458697.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/map_lane_segment.glb b/assets/models/map_lane_segment.glb new file mode 100644 index 0000000..8d5ef97 Binary files /dev/null and b/assets/models/map_lane_segment.glb differ diff --git a/assets/models/map_lane_segment.glb.import b/assets/models/map_lane_segment.glb.import new file mode 100644 index 0000000..139dccf --- /dev/null +++ b/assets/models/map_lane_segment.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://btjrh1f1ac7tn" +path="res://.godot/imported/map_lane_segment.glb-05555cf4745b726dd1e302d54bff4be2.scn" + +[deps] + +source_file="res://assets/models/map_lane_segment.glb" +dest_files=["res://.godot/imported/map_lane_segment.glb-05555cf4745b726dd1e302d54bff4be2.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g01.glb b/assets/models/unit_g01.glb new file mode 100644 index 0000000..a3e9601 Binary files /dev/null and b/assets/models/unit_g01.glb differ diff --git a/assets/models/unit_g01.glb.import b/assets/models/unit_g01.glb.import new file mode 100644 index 0000000..ca4d4af --- /dev/null +++ b/assets/models/unit_g01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cgg2t8vxwy0e0" +path="res://.godot/imported/unit_g01.glb-23ea40e143f3db2d1fbd1b76f2ba89fb.scn" + +[deps] + +source_file="res://assets/models/unit_g01.glb" +dest_files=["res://.godot/imported/unit_g01.glb-23ea40e143f3db2d1fbd1b76f2ba89fb.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g02.glb b/assets/models/unit_g02.glb new file mode 100644 index 0000000..f131a09 Binary files /dev/null and b/assets/models/unit_g02.glb differ diff --git a/assets/models/unit_g02.glb.import b/assets/models/unit_g02.glb.import new file mode 100644 index 0000000..0676c3e --- /dev/null +++ b/assets/models/unit_g02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dwj6fnl0f0uqe" +path="res://.godot/imported/unit_g02.glb-c1bfb800a14c7d738cfeae3065acb128.scn" + +[deps] + +source_file="res://assets/models/unit_g02.glb" +dest_files=["res://.godot/imported/unit_g02.glb-c1bfb800a14c7d738cfeae3065acb128.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g03.glb b/assets/models/unit_g03.glb new file mode 100644 index 0000000..a2cfab4 Binary files /dev/null and b/assets/models/unit_g03.glb differ diff --git a/assets/models/unit_g03.glb.import b/assets/models/unit_g03.glb.import new file mode 100644 index 0000000..b0cab3e --- /dev/null +++ b/assets/models/unit_g03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dp212df12xquf" +path="res://.godot/imported/unit_g03.glb-f61f056b084a4c936a7272421222a69e.scn" + +[deps] + +source_file="res://assets/models/unit_g03.glb" +dest_files=["res://.godot/imported/unit_g03.glb-f61f056b084a4c936a7272421222a69e.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g04.glb b/assets/models/unit_g04.glb new file mode 100644 index 0000000..e1694bb Binary files /dev/null and b/assets/models/unit_g04.glb differ diff --git a/assets/models/unit_g04.glb.import b/assets/models/unit_g04.glb.import new file mode 100644 index 0000000..d2c347b --- /dev/null +++ b/assets/models/unit_g04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://b70glpiobwjqp" +path="res://.godot/imported/unit_g04.glb-7e5c9db94ab13dc8f146fd3aad55cca4.scn" + +[deps] + +source_file="res://assets/models/unit_g04.glb" +dest_files=["res://.godot/imported/unit_g04.glb-7e5c9db94ab13dc8f146fd3aad55cca4.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g05.glb b/assets/models/unit_g05.glb new file mode 100644 index 0000000..184d357 Binary files /dev/null and b/assets/models/unit_g05.glb differ diff --git a/assets/models/unit_g05.glb.import b/assets/models/unit_g05.glb.import new file mode 100644 index 0000000..511ac74 --- /dev/null +++ b/assets/models/unit_g05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cf2xnjx55pokx" +path="res://.godot/imported/unit_g05.glb-4c86e24fafa3ecee011ee78f59c74056.scn" + +[deps] + +source_file="res://assets/models/unit_g05.glb" +dest_files=["res://.godot/imported/unit_g05.glb-4c86e24fafa3ecee011ee78f59c74056.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g06.glb b/assets/models/unit_g06.glb new file mode 100644 index 0000000..c46096a Binary files /dev/null and b/assets/models/unit_g06.glb differ diff --git a/assets/models/unit_g06.glb.import b/assets/models/unit_g06.glb.import new file mode 100644 index 0000000..af7d22d --- /dev/null +++ b/assets/models/unit_g06.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://77fy0poewfx2" +path="res://.godot/imported/unit_g06.glb-5a5293d5526630120da6c13079496591.scn" + +[deps] + +source_file="res://assets/models/unit_g06.glb" +dest_files=["res://.godot/imported/unit_g06.glb-5a5293d5526630120da6c13079496591.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g07.glb b/assets/models/unit_g07.glb new file mode 100644 index 0000000..53b7700 Binary files /dev/null and b/assets/models/unit_g07.glb differ diff --git a/assets/models/unit_g07.glb.import b/assets/models/unit_g07.glb.import new file mode 100644 index 0000000..e85d870 --- /dev/null +++ b/assets/models/unit_g07.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://nm4yskumi7b4" +path="res://.godot/imported/unit_g07.glb-25af5d21808ca4c5ab6bf5c1cdad70e8.scn" + +[deps] + +source_file="res://assets/models/unit_g07.glb" +dest_files=["res://.godot/imported/unit_g07.glb-25af5d21808ca4c5ab6bf5c1cdad70e8.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g08.glb b/assets/models/unit_g08.glb new file mode 100644 index 0000000..df93b17 Binary files /dev/null and b/assets/models/unit_g08.glb differ diff --git a/assets/models/unit_g08.glb.import b/assets/models/unit_g08.glb.import new file mode 100644 index 0000000..21073bb --- /dev/null +++ b/assets/models/unit_g08.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://86i2exo4xs2u" +path="res://.godot/imported/unit_g08.glb-a90602db19d63ba3af6cf69c226ff1e9.scn" + +[deps] + +source_file="res://assets/models/unit_g08.glb" +dest_files=["res://.godot/imported/unit_g08.glb-a90602db19d63ba3af6cf69c226ff1e9.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g09.glb b/assets/models/unit_g09.glb new file mode 100644 index 0000000..270a6d3 Binary files /dev/null and b/assets/models/unit_g09.glb differ diff --git a/assets/models/unit_g09.glb.import b/assets/models/unit_g09.glb.import new file mode 100644 index 0000000..1852270 --- /dev/null +++ b/assets/models/unit_g09.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c514n1tvo5x16" +path="res://.godot/imported/unit_g09.glb-3e217ccb086526828be434abcf65587b.scn" + +[deps] + +source_file="res://assets/models/unit_g09.glb" +dest_files=["res://.godot/imported/unit_g09.glb-3e217ccb086526828be434abcf65587b.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_g10.glb b/assets/models/unit_g10.glb new file mode 100644 index 0000000..cc7158d Binary files /dev/null and b/assets/models/unit_g10.glb differ diff --git a/assets/models/unit_g10.glb.import b/assets/models/unit_g10.glb.import new file mode 100644 index 0000000..bc45bf0 --- /dev/null +++ b/assets/models/unit_g10.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cdkasjerp30au" +path="res://.godot/imported/unit_g10.glb-ed4af4354dfaeb8b96c5970295aa1d11.scn" + +[deps] + +source_file="res://assets/models/unit_g10.glb" +dest_files=["res://.godot/imported/unit_g10.glb-ed4af4354dfaeb8b96c5970295aa1d11.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m01.glb b/assets/models/unit_m01.glb new file mode 100644 index 0000000..785218b Binary files /dev/null and b/assets/models/unit_m01.glb differ diff --git a/assets/models/unit_m01.glb.import b/assets/models/unit_m01.glb.import new file mode 100644 index 0000000..8dca214 --- /dev/null +++ b/assets/models/unit_m01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://u0vjnv8t0oim" +path="res://.godot/imported/unit_m01.glb-4b9253c877851ed887d4b7b9c037cbb1.scn" + +[deps] + +source_file="res://assets/models/unit_m01.glb" +dest_files=["res://.godot/imported/unit_m01.glb-4b9253c877851ed887d4b7b9c037cbb1.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m02.glb b/assets/models/unit_m02.glb new file mode 100644 index 0000000..3baa050 Binary files /dev/null and b/assets/models/unit_m02.glb differ diff --git a/assets/models/unit_m02.glb.import b/assets/models/unit_m02.glb.import new file mode 100644 index 0000000..8a48ae3 --- /dev/null +++ b/assets/models/unit_m02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dwbarcha4o7g5" +path="res://.godot/imported/unit_m02.glb-3a3c5dddbe9735315fa5139d1be6d320.scn" + +[deps] + +source_file="res://assets/models/unit_m02.glb" +dest_files=["res://.godot/imported/unit_m02.glb-3a3c5dddbe9735315fa5139d1be6d320.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m03.glb b/assets/models/unit_m03.glb new file mode 100644 index 0000000..8cb3e2a Binary files /dev/null and b/assets/models/unit_m03.glb differ diff --git a/assets/models/unit_m03.glb.import b/assets/models/unit_m03.glb.import new file mode 100644 index 0000000..0117a84 --- /dev/null +++ b/assets/models/unit_m03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://m847i6oj1rre" +path="res://.godot/imported/unit_m03.glb-fa9347e87944dfbc6292f4af32f45354.scn" + +[deps] + +source_file="res://assets/models/unit_m03.glb" +dest_files=["res://.godot/imported/unit_m03.glb-fa9347e87944dfbc6292f4af32f45354.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m04.glb b/assets/models/unit_m04.glb new file mode 100644 index 0000000..a4f38bb Binary files /dev/null and b/assets/models/unit_m04.glb differ diff --git a/assets/models/unit_m04.glb.import b/assets/models/unit_m04.glb.import new file mode 100644 index 0000000..105868e --- /dev/null +++ b/assets/models/unit_m04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ce3vid4yugao8" +path="res://.godot/imported/unit_m04.glb-a691c7daa8633bc03fb7016d91b97149.scn" + +[deps] + +source_file="res://assets/models/unit_m04.glb" +dest_files=["res://.godot/imported/unit_m04.glb-a691c7daa8633bc03fb7016d91b97149.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m05.glb b/assets/models/unit_m05.glb new file mode 100644 index 0000000..cb13248 Binary files /dev/null and b/assets/models/unit_m05.glb differ diff --git a/assets/models/unit_m05.glb.import b/assets/models/unit_m05.glb.import new file mode 100644 index 0000000..5260438 --- /dev/null +++ b/assets/models/unit_m05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://k0gm1wxu2ik" +path="res://.godot/imported/unit_m05.glb-629e2259dec77a140789373f71082a46.scn" + +[deps] + +source_file="res://assets/models/unit_m05.glb" +dest_files=["res://.godot/imported/unit_m05.glb-629e2259dec77a140789373f71082a46.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m06.glb b/assets/models/unit_m06.glb new file mode 100644 index 0000000..c843e5b Binary files /dev/null and b/assets/models/unit_m06.glb differ diff --git a/assets/models/unit_m06.glb.import b/assets/models/unit_m06.glb.import new file mode 100644 index 0000000..ec55101 --- /dev/null +++ b/assets/models/unit_m06.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bmdft1amahi0q" +path="res://.godot/imported/unit_m06.glb-e3fe87b979752c2706f8fe7861e50604.scn" + +[deps] + +source_file="res://assets/models/unit_m06.glb" +dest_files=["res://.godot/imported/unit_m06.glb-e3fe87b979752c2706f8fe7861e50604.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m07.glb b/assets/models/unit_m07.glb new file mode 100644 index 0000000..ab9ca74 Binary files /dev/null and b/assets/models/unit_m07.glb differ diff --git a/assets/models/unit_m07.glb.import b/assets/models/unit_m07.glb.import new file mode 100644 index 0000000..458688e --- /dev/null +++ b/assets/models/unit_m07.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bhv2q8c0kklis" +path="res://.godot/imported/unit_m07.glb-eb2edf8121220f57cd4f4769759881b8.scn" + +[deps] + +source_file="res://assets/models/unit_m07.glb" +dest_files=["res://.godot/imported/unit_m07.glb-eb2edf8121220f57cd4f4769759881b8.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m08.glb b/assets/models/unit_m08.glb new file mode 100644 index 0000000..9eb08de Binary files /dev/null and b/assets/models/unit_m08.glb differ diff --git a/assets/models/unit_m08.glb.import b/assets/models/unit_m08.glb.import new file mode 100644 index 0000000..3e590ef --- /dev/null +++ b/assets/models/unit_m08.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://drlig58m27k1y" +path="res://.godot/imported/unit_m08.glb-a3f6add9305449bfc58c130baab093cd.scn" + +[deps] + +source_file="res://assets/models/unit_m08.glb" +dest_files=["res://.godot/imported/unit_m08.glb-a3f6add9305449bfc58c130baab093cd.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m09.glb b/assets/models/unit_m09.glb new file mode 100644 index 0000000..7373ade Binary files /dev/null and b/assets/models/unit_m09.glb differ diff --git a/assets/models/unit_m09.glb.import b/assets/models/unit_m09.glb.import new file mode 100644 index 0000000..95af428 --- /dev/null +++ b/assets/models/unit_m09.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://df0lo5cq4muni" +path="res://.godot/imported/unit_m09.glb-563035cfbdf4c25ab2d420fb2d094f98.scn" + +[deps] + +source_file="res://assets/models/unit_m09.glb" +dest_files=["res://.godot/imported/unit_m09.glb-563035cfbdf4c25ab2d420fb2d094f98.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_m10.glb b/assets/models/unit_m10.glb new file mode 100644 index 0000000..062c0c9 Binary files /dev/null and b/assets/models/unit_m10.glb differ diff --git a/assets/models/unit_m10.glb.import b/assets/models/unit_m10.glb.import new file mode 100644 index 0000000..380652d --- /dev/null +++ b/assets/models/unit_m10.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://vofk4qgetyje" +path="res://.godot/imported/unit_m10.glb-453a53c8c66940819e6dbae13b751e2a.scn" + +[deps] + +source_file="res://assets/models/unit_m10.glb" +dest_files=["res://.godot/imported/unit_m10.glb-453a53c8c66940819e6dbae13b751e2a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n01.glb b/assets/models/unit_n01.glb new file mode 100644 index 0000000..c2432bb Binary files /dev/null and b/assets/models/unit_n01.glb differ diff --git a/assets/models/unit_n01.glb.import b/assets/models/unit_n01.glb.import new file mode 100644 index 0000000..a437318 --- /dev/null +++ b/assets/models/unit_n01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://d08windf3d7nk" +path="res://.godot/imported/unit_n01.glb-3772da3e71a73e10b5c225ccaa0e6cd5.scn" + +[deps] + +source_file="res://assets/models/unit_n01.glb" +dest_files=["res://.godot/imported/unit_n01.glb-3772da3e71a73e10b5c225ccaa0e6cd5.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n02.glb b/assets/models/unit_n02.glb new file mode 100644 index 0000000..bcb8a9b Binary files /dev/null and b/assets/models/unit_n02.glb differ diff --git a/assets/models/unit_n02.glb.import b/assets/models/unit_n02.glb.import new file mode 100644 index 0000000..a0a102d --- /dev/null +++ b/assets/models/unit_n02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://2lpd65f8qxoq" +path="res://.godot/imported/unit_n02.glb-da261018032b0568010200f5f8a8a5ea.scn" + +[deps] + +source_file="res://assets/models/unit_n02.glb" +dest_files=["res://.godot/imported/unit_n02.glb-da261018032b0568010200f5f8a8a5ea.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n03.glb b/assets/models/unit_n03.glb new file mode 100644 index 0000000..bee861a Binary files /dev/null and b/assets/models/unit_n03.glb differ diff --git a/assets/models/unit_n03.glb.import b/assets/models/unit_n03.glb.import new file mode 100644 index 0000000..ff3bb61 --- /dev/null +++ b/assets/models/unit_n03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dpaiijba2frkw" +path="res://.godot/imported/unit_n03.glb-fe9030172b8bffe309dc581bd7fb53df.scn" + +[deps] + +source_file="res://assets/models/unit_n03.glb" +dest_files=["res://.godot/imported/unit_n03.glb-fe9030172b8bffe309dc581bd7fb53df.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n04.glb b/assets/models/unit_n04.glb new file mode 100644 index 0000000..3814109 Binary files /dev/null and b/assets/models/unit_n04.glb differ diff --git a/assets/models/unit_n04.glb.import b/assets/models/unit_n04.glb.import new file mode 100644 index 0000000..7b0bcda --- /dev/null +++ b/assets/models/unit_n04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://lluchdq10mdm" +path="res://.godot/imported/unit_n04.glb-2eed8a5e321c08f356ae512da59d461b.scn" + +[deps] + +source_file="res://assets/models/unit_n04.glb" +dest_files=["res://.godot/imported/unit_n04.glb-2eed8a5e321c08f356ae512da59d461b.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n05.glb b/assets/models/unit_n05.glb new file mode 100644 index 0000000..e3a3279 Binary files /dev/null and b/assets/models/unit_n05.glb differ diff --git a/assets/models/unit_n05.glb.import b/assets/models/unit_n05.glb.import new file mode 100644 index 0000000..92d916d --- /dev/null +++ b/assets/models/unit_n05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c83bycuhtpbnc" +path="res://.godot/imported/unit_n05.glb-4586d5ce86e348f746d0b00b8a8e632f.scn" + +[deps] + +source_file="res://assets/models/unit_n05.glb" +dest_files=["res://.godot/imported/unit_n05.glb-4586d5ce86e348f746d0b00b8a8e632f.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n06.glb b/assets/models/unit_n06.glb new file mode 100644 index 0000000..6a0a1f4 Binary files /dev/null and b/assets/models/unit_n06.glb differ diff --git a/assets/models/unit_n06.glb.import b/assets/models/unit_n06.glb.import new file mode 100644 index 0000000..4c5918e --- /dev/null +++ b/assets/models/unit_n06.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bvfrginqmbo5g" +path="res://.godot/imported/unit_n06.glb-d8826cdc7c9eaf74b8693125e34eee71.scn" + +[deps] + +source_file="res://assets/models/unit_n06.glb" +dest_files=["res://.godot/imported/unit_n06.glb-d8826cdc7c9eaf74b8693125e34eee71.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n07.glb b/assets/models/unit_n07.glb new file mode 100644 index 0000000..3fe1a58 Binary files /dev/null and b/assets/models/unit_n07.glb differ diff --git a/assets/models/unit_n07.glb.import b/assets/models/unit_n07.glb.import new file mode 100644 index 0000000..c019e2e --- /dev/null +++ b/assets/models/unit_n07.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://oikpslx3uvps" +path="res://.godot/imported/unit_n07.glb-c5a373e2d6bbdb2b86b2a23165e2401a.scn" + +[deps] + +source_file="res://assets/models/unit_n07.glb" +dest_files=["res://.godot/imported/unit_n07.glb-c5a373e2d6bbdb2b86b2a23165e2401a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n08.glb b/assets/models/unit_n08.glb new file mode 100644 index 0000000..4ada29a Binary files /dev/null and b/assets/models/unit_n08.glb differ diff --git a/assets/models/unit_n08.glb.import b/assets/models/unit_n08.glb.import new file mode 100644 index 0000000..596f76f --- /dev/null +++ b/assets/models/unit_n08.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dn206prmpvx3y" +path="res://.godot/imported/unit_n08.glb-921d9e9ff1f74eee0e7530af654614b3.scn" + +[deps] + +source_file="res://assets/models/unit_n08.glb" +dest_files=["res://.godot/imported/unit_n08.glb-921d9e9ff1f74eee0e7530af654614b3.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n09.glb b/assets/models/unit_n09.glb new file mode 100644 index 0000000..b3e336b Binary files /dev/null and b/assets/models/unit_n09.glb differ diff --git a/assets/models/unit_n09.glb.import b/assets/models/unit_n09.glb.import new file mode 100644 index 0000000..e5aa915 --- /dev/null +++ b/assets/models/unit_n09.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dtqja3dykqq5r" +path="res://.godot/imported/unit_n09.glb-0235f0216a5942514bfe6f72d2985fa2.scn" + +[deps] + +source_file="res://assets/models/unit_n09.glb" +dest_files=["res://.godot/imported/unit_n09.glb-0235f0216a5942514bfe6f72d2985fa2.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_n10.glb b/assets/models/unit_n10.glb new file mode 100644 index 0000000..887d624 Binary files /dev/null and b/assets/models/unit_n10.glb differ diff --git a/assets/models/unit_n10.glb.import b/assets/models/unit_n10.glb.import new file mode 100644 index 0000000..57e5480 --- /dev/null +++ b/assets/models/unit_n10.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c6ftks1q4452s" +path="res://.godot/imported/unit_n10.glb-a24a980d31c5ff13d6fa84e280c6b9fa.scn" + +[deps] + +source_file="res://assets/models/unit_n10.glb" +dest_files=["res://.godot/imported/unit_n10.glb-a24a980d31c5ff13d6fa84e280c6b9fa.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_s01.glb b/assets/models/unit_s01.glb new file mode 100644 index 0000000..d704d50 Binary files /dev/null and b/assets/models/unit_s01.glb differ diff --git a/assets/models/unit_s01.glb.import b/assets/models/unit_s01.glb.import new file mode 100644 index 0000000..72e4a77 --- /dev/null +++ b/assets/models/unit_s01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://cmhbst4t631l3" +path="res://.godot/imported/unit_s01.glb-be873aba5d7e6832ae03afcbe61af39d.scn" + +[deps] + +source_file="res://assets/models/unit_s01.glb" +dest_files=["res://.godot/imported/unit_s01.glb-be873aba5d7e6832ae03afcbe61af39d.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_s02.glb b/assets/models/unit_s02.glb new file mode 100644 index 0000000..82691fc Binary files /dev/null and b/assets/models/unit_s02.glb differ diff --git a/assets/models/unit_s02.glb.import b/assets/models/unit_s02.glb.import new file mode 100644 index 0000000..9e4dd6b --- /dev/null +++ b/assets/models/unit_s02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dkyxdwxvbqqsm" +path="res://.godot/imported/unit_s02.glb-2b28311b2affeb5a4cf6440a5629bdec.scn" + +[deps] + +source_file="res://assets/models/unit_s02.glb" +dest_files=["res://.godot/imported/unit_s02.glb-2b28311b2affeb5a4cf6440a5629bdec.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_s03.glb b/assets/models/unit_s03.glb new file mode 100644 index 0000000..f7469b9 Binary files /dev/null and b/assets/models/unit_s03.glb differ diff --git a/assets/models/unit_s03.glb.import b/assets/models/unit_s03.glb.import new file mode 100644 index 0000000..ac4668c --- /dev/null +++ b/assets/models/unit_s03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://crmc15gf60p3a" +path="res://.godot/imported/unit_s03.glb-0fcb5608c922b3d67bc1e048066265a2.scn" + +[deps] + +source_file="res://assets/models/unit_s03.glb" +dest_files=["res://.godot/imported/unit_s03.glb-0fcb5608c922b3d67bc1e048066265a2.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_s04.glb b/assets/models/unit_s04.glb new file mode 100644 index 0000000..c9a2837 Binary files /dev/null and b/assets/models/unit_s04.glb differ diff --git a/assets/models/unit_s04.glb.import b/assets/models/unit_s04.glb.import new file mode 100644 index 0000000..607c96f --- /dev/null +++ b/assets/models/unit_s04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://j6q0x7njvudg" +path="res://.godot/imported/unit_s04.glb-6dd8e8f0739970029e0f08167d3807d7.scn" + +[deps] + +source_file="res://assets/models/unit_s04.glb" +dest_files=["res://.godot/imported/unit_s04.glb-6dd8e8f0739970029e0f08167d3807d7.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_s05.glb b/assets/models/unit_s05.glb new file mode 100644 index 0000000..785fbbc Binary files /dev/null and b/assets/models/unit_s05.glb differ diff --git a/assets/models/unit_s05.glb.import b/assets/models/unit_s05.glb.import new file mode 100644 index 0000000..da1996a --- /dev/null +++ b/assets/models/unit_s05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dgmiyaq5txepv" +path="res://.godot/imported/unit_s05.glb-0e26f4b9479615abe591f479f7dbcbe1.scn" + +[deps] + +source_file="res://assets/models/unit_s05.glb" +dest_files=["res://.godot/imported/unit_s05.glb-0e26f4b9479615abe591f479f7dbcbe1.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w01.glb b/assets/models/unit_w01.glb new file mode 100644 index 0000000..ec3f7ae Binary files /dev/null and b/assets/models/unit_w01.glb differ diff --git a/assets/models/unit_w01.glb.import b/assets/models/unit_w01.glb.import new file mode 100644 index 0000000..5df31a9 --- /dev/null +++ b/assets/models/unit_w01.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://c4bq3y8d68bjd" +path="res://.godot/imported/unit_w01.glb-d6270a4bf32c4b8bb55bba362e69077d.scn" + +[deps] + +source_file="res://assets/models/unit_w01.glb" +dest_files=["res://.godot/imported/unit_w01.glb-d6270a4bf32c4b8bb55bba362e69077d.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w02.glb b/assets/models/unit_w02.glb new file mode 100644 index 0000000..6d3249a Binary files /dev/null and b/assets/models/unit_w02.glb differ diff --git a/assets/models/unit_w02.glb.import b/assets/models/unit_w02.glb.import new file mode 100644 index 0000000..ab2d281 --- /dev/null +++ b/assets/models/unit_w02.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://wneo1v4k7lwn" +path="res://.godot/imported/unit_w02.glb-d94ab5c01c2a3c87085641b181e3300b.scn" + +[deps] + +source_file="res://assets/models/unit_w02.glb" +dest_files=["res://.godot/imported/unit_w02.glb-d94ab5c01c2a3c87085641b181e3300b.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w03.glb b/assets/models/unit_w03.glb new file mode 100644 index 0000000..a6bdec1 Binary files /dev/null and b/assets/models/unit_w03.glb differ diff --git a/assets/models/unit_w03.glb.import b/assets/models/unit_w03.glb.import new file mode 100644 index 0000000..3cdc47d --- /dev/null +++ b/assets/models/unit_w03.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://mtjy8pjaovv0" +path="res://.godot/imported/unit_w03.glb-5e3f0e816b7546198b7dffc7a53c1f0e.scn" + +[deps] + +source_file="res://assets/models/unit_w03.glb" +dest_files=["res://.godot/imported/unit_w03.glb-5e3f0e816b7546198b7dffc7a53c1f0e.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w04.glb b/assets/models/unit_w04.glb new file mode 100644 index 0000000..a845c85 Binary files /dev/null and b/assets/models/unit_w04.glb differ diff --git a/assets/models/unit_w04.glb.import b/assets/models/unit_w04.glb.import new file mode 100644 index 0000000..4f493b4 --- /dev/null +++ b/assets/models/unit_w04.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bfdiisfdlbk4s" +path="res://.godot/imported/unit_w04.glb-04ee53a9623a142aad670e39aef0a584.scn" + +[deps] + +source_file="res://assets/models/unit_w04.glb" +dest_files=["res://.godot/imported/unit_w04.glb-04ee53a9623a142aad670e39aef0a584.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w05.glb b/assets/models/unit_w05.glb new file mode 100644 index 0000000..0270bfd Binary files /dev/null and b/assets/models/unit_w05.glb differ diff --git a/assets/models/unit_w05.glb.import b/assets/models/unit_w05.glb.import new file mode 100644 index 0000000..9f08699 --- /dev/null +++ b/assets/models/unit_w05.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dpigqk6mu6135" +path="res://.godot/imported/unit_w05.glb-165fb2b8951e407e0145155b04022d5a.scn" + +[deps] + +source_file="res://assets/models/unit_w05.glb" +dest_files=["res://.godot/imported/unit_w05.glb-165fb2b8951e407e0145155b04022d5a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w06.glb b/assets/models/unit_w06.glb new file mode 100644 index 0000000..d626a7e Binary files /dev/null and b/assets/models/unit_w06.glb differ diff --git a/assets/models/unit_w06.glb.import b/assets/models/unit_w06.glb.import new file mode 100644 index 0000000..3613551 --- /dev/null +++ b/assets/models/unit_w06.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ck4tmmb0q8iyg" +path="res://.godot/imported/unit_w06.glb-4f6159d6ebb449516d14f70290aac494.scn" + +[deps] + +source_file="res://assets/models/unit_w06.glb" +dest_files=["res://.godot/imported/unit_w06.glb-4f6159d6ebb449516d14f70290aac494.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w07.glb b/assets/models/unit_w07.glb new file mode 100644 index 0000000..8e30eb2 Binary files /dev/null and b/assets/models/unit_w07.glb differ diff --git a/assets/models/unit_w07.glb.import b/assets/models/unit_w07.glb.import new file mode 100644 index 0000000..919eaac --- /dev/null +++ b/assets/models/unit_w07.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://6lmvi55he3e4" +path="res://.godot/imported/unit_w07.glb-a0948131b8ae5594212e70bb695e9e0f.scn" + +[deps] + +source_file="res://assets/models/unit_w07.glb" +dest_files=["res://.godot/imported/unit_w07.glb-a0948131b8ae5594212e70bb695e9e0f.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w08.glb b/assets/models/unit_w08.glb new file mode 100644 index 0000000..b0f31fd Binary files /dev/null and b/assets/models/unit_w08.glb differ diff --git a/assets/models/unit_w08.glb.import b/assets/models/unit_w08.glb.import new file mode 100644 index 0000000..cc015d9 --- /dev/null +++ b/assets/models/unit_w08.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bolqvc8dfpdde" +path="res://.godot/imported/unit_w08.glb-2967c2b56289ddce9b4b427aecc19621.scn" + +[deps] + +source_file="res://assets/models/unit_w08.glb" +dest_files=["res://.godot/imported/unit_w08.glb-2967c2b56289ddce9b4b427aecc19621.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w09.glb b/assets/models/unit_w09.glb new file mode 100644 index 0000000..34483e2 Binary files /dev/null and b/assets/models/unit_w09.glb differ diff --git a/assets/models/unit_w09.glb.import b/assets/models/unit_w09.glb.import new file mode 100644 index 0000000..6e7aa4f --- /dev/null +++ b/assets/models/unit_w09.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://dlye7t2wx8jjr" +path="res://.godot/imported/unit_w09.glb-4bd0c3496946df240bcd6032ef173ac0.scn" + +[deps] + +source_file="res://assets/models/unit_w09.glb" +dest_files=["res://.godot/imported/unit_w09.glb-4bd0c3496946df240bcd6032ef173ac0.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/unit_w10.glb b/assets/models/unit_w10.glb new file mode 100644 index 0000000..c1fb489 Binary files /dev/null and b/assets/models/unit_w10.glb differ diff --git a/assets/models/unit_w10.glb.import b/assets/models/unit_w10.glb.import new file mode 100644 index 0000000..b5756e4 --- /dev/null +++ b/assets/models/unit_w10.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://swux744w5bb1" +path="res://.godot/imported/unit_w10.glb-e8cae4a408fa4f37077e3d431f5f9f2b.scn" + +[deps] + +source_file="res://assets/models/unit_w10.glb" +dest_files=["res://.godot/imported/unit_w10.glb-e8cae4a408fa4f37077e3d431f5f9f2b.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/models/worker.glb b/assets/models/worker.glb new file mode 100644 index 0000000..52e4f55 Binary files /dev/null and b/assets/models/worker.glb differ diff --git a/assets/models/worker.glb.import b/assets/models/worker.glb.import new file mode 100644 index 0000000..1df01cb --- /dev/null +++ b/assets/models/worker.glb.import @@ -0,0 +1,45 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://smvofq7dvy64" +path="res://.godot/imported/worker.glb-b1e09b27d2484c4047acc38fa6c44ad6.scn" + +[deps] + +source_file="res://assets/models/worker.glb" +dest_files=["res://.godot/imported/worker.glb-b1e09b27d2484c4047acc38fa6c44ad6.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/root_script=null +mesh_library/use_node_names_as_mesh_names=false +array_mesh/deduplicate_surfaces=true +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_name_suffixes=true +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +materials/extract=0 +materials/extract_format=0 +materials/extract_path="" +_subresources={} +gltf/naming_version=2 +gltf/embedded_image_handling=1 +gltf/texture_map_mode=1 diff --git a/assets/phase11_manifest.json b/assets/phase11_manifest.json new file mode 100644 index 0000000..368381c --- /dev/null +++ b/assets/phase11_manifest.json @@ -0,0 +1,41 @@ +{ + "assets": [ + { + "id": "w04", + "role": "tank", + "resource_path": "res://assets/characters/ringborke.glb", + "triangles": 118064, + "mesh_parts": 1, + "parts": [ + "RingborkeBody" + ], + "bounds_godot": { + "min": [ + -0.9736061096191406, + 0.010707742534577847, + -0.3616310954093933 + ], + "max": [ + 0.977129340171814, + 1.8529540300369263, + 0.3701480031013489 + ] + }, + "skeletal": true, + "bones": 27, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "sha256": "a9c61bcb7ae957c3e6b035ef994db3c8736b7a5f89d62724162dd606b76895b8", + "source": "assets-source/phase11/ringborke.blend" + } + ] +} diff --git a/assets/phase12_manifest.json b/assets/phase12_manifest.json new file mode 100644 index 0000000..e69b0ea --- /dev/null +++ b/assets/phase12_manifest.json @@ -0,0 +1,63 @@ +{ + "assets": [ + { + "id": "worker", + "role": "worker", + "name": "Funkenleser", + "resource_path": "res://assets/characters/arbeiter.glb", + "triangles": 7184, + "mesh_parts": 1, + "parts": [ + "ArbeiterBody" + ], + "bounds_godot": { + "min": [ + -0.4699999988079071, + -0.10096755623817444, + -0.3050000071525574 + ], + "max": [ + 0.4281836748123169, + 1.2300000190734863, + 0.31158649921417236 + ] + }, + "skeletal": true, + "bones": 27, + "clips": [ + "idle", + "start", + "walk", + "stop", + "strike", + "pickup", + "deposit", + "return", + "hit", + "death" + ], + "work_cycle": [ + "strike", + "pickup", + "deposit", + "return" + ], + "sha256": "6b61389e6806cf130376665bcf791c5948e070a49593702faebaafad52d7d6d2", + "source": "assets-source/phase12/arbeiter.blend" + } + ], + "cores": [ + { + "id": "core_team0", + "activate_clip": "activate", + "operate_clip": "operate", + "damage_clip": "damage" + }, + { + "id": "core_team1", + "activate_clip": "activate", + "operate_clip": "operate", + "damage_clip": "damage" + } + ] +} diff --git a/assets/phase15_manifest.json b/assets/phase15_manifest.json new file mode 100644 index 0000000..b56c64e --- /dev/null +++ b/assets/phase15_manifest.json @@ -0,0 +1,42 @@ +{ + "assets": [ + { + "id": "g04", + "role": "tank", + "name": "Basaltbastion", + "resource_path": "res://assets/characters/basaltbastion.glb", + "triangles": 17824, + "mesh_parts": 1, + "parts": [ + "BasaltBody" + ], + "bounds_godot": { + "min": [ + -0.8817209601402283, + -0.019999999552965164, + -0.46514952182769775 + ], + "max": [ + 0.8817209601402283, + 2.2275519371032715, + 0.3866296112537384 + ] + }, + "skeletal": true, + "bones": 17, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "sha256": "af7ec19ee2714f4bd884b61af15b225b79be7efea7aefa73a706fe981cafdbbe", + "source": "assets-source/phase15/basaltbastion.blend" + } + ] +} diff --git a/assets/phase16_manifest.json b/assets/phase16_manifest.json new file mode 100644 index 0000000..b99ac97 --- /dev/null +++ b/assets/phase16_manifest.json @@ -0,0 +1,42 @@ +{ + "assets": [ + { + "id": "w10", + "role": "support", + "name": "Quellgeflecht", + "resource_path": "res://assets/characters/quellgeflecht.glb", + "triangles": 14276, + "mesh_parts": 1, + "parts": [ + "QuellBody" + ], + "bounds_godot": { + "min": [ + -0.8399999737739563, + -0.011425986886024475, + -0.2583521902561188 + ], + "max": [ + 0.8399999737739563, + 1.8600000143051147, + 0.42399999499320984 + ] + }, + "skeletal": true, + "bones": 17, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "sha256": "52de3d57191b85a0053cc3049f298801d07c17266c08364cfa0da68e94b4614a", + "source": "assets-source/phase16/quellgeflecht.blend" + } + ] +} diff --git a/assets/phase18_manifest.json b/assets/phase18_manifest.json new file mode 100644 index 0000000..786c4d3 --- /dev/null +++ b/assets/phase18_manifest.json @@ -0,0 +1,49 @@ +{ + "assets": [ + { + "id": "g05", + "role": "ranged", + "name": "Funkenlanze", + "resource_path": "res://assets/characters/funkenlanze.glb", + "triangles": 24036, + "mesh_parts": 1, + "parts": [ + "FunkenBody" + ], + "bounds_godot": { + "min": [ + -0.4300000071525574, + -0.010409347712993622, + -0.2945486903190613 + ], + "max": [ + 0.5651692152023315, + 2.021195411682129, + 1.4350000619888306 + ] + }, + "skeletal": true, + "bones": 26, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "attack_cycle": [ + "attack_a", + "attack_b", + "attack_a", + "ability" + ], + "contact_seconds": 0.9, + "sha256": "cc075b6e69ee3d25cf19ec9da8ecde6f0bcc7e98f7e5400ff214061fd8af67fd", + "source": "assets-source/phase18/funkenlanze.blend" + } + ] +} diff --git a/assets/phase19_manifest.json b/assets/phase19_manifest.json new file mode 100644 index 0000000..217b43b --- /dev/null +++ b/assets/phase19_manifest.json @@ -0,0 +1,49 @@ +{ + "assets": [ + { + "id": "g06", + "role": "ranged", + "name": "Glasballiste", + "resource_path": "res://assets/characters/glasballiste.glb", + "triangles": 15784, + "mesh_parts": 1, + "parts": [ + "GlassBody" + ], + "bounds_godot": { + "min": [ + -0.9268030524253845, + 0.0010433457791805267, + -0.6150000095367432 + ], + "max": [ + 0.9268030524253845, + 1.434999942779541, + 1.0 + ] + }, + "skeletal": true, + "bones": 20, + "clips": [ + "idle", + "start", + "walk", + "stop", + "attack_a", + "attack_b", + "hit", + "ability", + "death" + ], + "attack_cycle": [ + "attack_a", + "attack_b", + "attack_a", + "ability" + ], + "contact_seconds": 0.9, + "sha256": "c2f8a526b0b7006b549342561346acd5478406c33c5a79678f63f7c76f583dd8", + "source": "assets-source/phase19/glasballiste.blend" + } + ] +} diff --git a/assets/phase3_manifest.json b/assets/phase3_manifest.json new file mode 100644 index 0000000..00cf729 --- /dev/null +++ b/assets/phase3_manifest.json @@ -0,0 +1,1447 @@ +{ + "phase": 3, + "asset_count": 66, + "note": "Native PNG masters; 56 icon textures use a Godot import limit of 256px. Gameplay integration follows in Phase 5.", + "assets": [ + { + "id": "g01", + "display_name": "Kohlenbeißer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter Basaltkörper mit glühendem Maul, kräftigen Klauen und Messingakzenten.", + "resource_path": "res://assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g01_kohlenbeisser_icon.png", + "record_path": "assets-source/phase3/records/g01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "762bdd4aa646d58d7f1b2d1d39bb082d68b0d600955f73dfa839bd999554d97a", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g02", + "display_name": "Schlackenklaue", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwer gepanzerter Kohlenkörper mit breiten Basaltschultern, glühendem Maul und großen messingbesetzten Klauen.", + "resource_path": "res://assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g02_schlackenklaue_icon.png", + "record_path": "assets-source/phase3/records/g02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7c1ddff3a11e033ba0c105fcdb3a6a16a919b2aa30e4a56c0bf1be1b1e7ce1db", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g03", + "display_name": "Schlackenwacht", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Basaltwächter mit breiter Schildfront, schmaler Ofenglut und kurzen, kräftigen Armen.", + "resource_path": "res://assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g03_schlackenwacht_icon.png", + "record_path": "assets-source/phase3/records/g03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7f9d69bcd387551f69370bada56fa25f7ca00f4d00bcc5d144dea15635988708", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g04", + "display_name": "Basaltbastion", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Lebende Basaltfestung mit gestuften Schultern, gepanzerter Schildfront und glühendem Ofenkern.", + "resource_path": "res://assets/icons/glutpakt/unit_g04_basaltbastion_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g04_basaltbastion_icon.png", + "record_path": "assets-source/phase3/records/g04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "2efa23fa99c3c85cf582bd0132e4db9fb454a8feedb81b4e6149e98ba999b1b9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g05", + "display_name": "Funkenlanze", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Glutkonstrukt-Schütze mit langer Messinglanze und orange leuchtender Glasspitze.", + "resource_path": "res://assets/icons/glutpakt/unit_g05_funkenlanze_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g05_funkenlanze_icon.png", + "record_path": "assets-source/phase3/records/g05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c0883dc35abb007dcda5906a04ae29be995f4f80d4db7c1ab368de3b4addb519", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g06", + "display_name": "Glasballiste", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Bewegliche Glasballiste mit großen orangefarbenen Kristallarmen, langem Bolzen und stabilem Basaltunterbau.", + "resource_path": "res://assets/icons/glutpakt/unit_g06_glasballiste_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g06_glasballiste_icon.png", + "record_path": "assets-source/phase3/records/g06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c1eedabf95f65b662dd0ad5adda16b264bbb8121d23627cf6d9c0e646cf4669e", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g07", + "display_name": "Aschenwerfer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Aschenwerfer mit breitem Mörserkelch, glühender Kohle und kurzen Basaltbeinen.", + "resource_path": "res://assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g07_aschenwerfer_icon.png", + "record_path": "assets-source/phase3/records/g07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "38783c17d025f293fbe21086ee737eeb31fc5cb7152a4b24e066929e21684052", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g08", + "display_name": "Kraterrufer", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwerer Kraterkörper mit großem Vulkankelch, glühendem Inneren und gestuften Basaltplatten.", + "resource_path": "res://assets/icons/glutpakt/unit_g08_kraterrufer_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g08_kraterrufer_icon.png", + "record_path": "assets-source/phase3/records/g08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "141b2787c3fb0abdd3be30c628bbc5f767bf865a8576580194727b453f64c07c", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g09", + "display_name": "Herdhüter", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Herdwächter mit offenem Glutofen und einer schützenden Messingschale vor dem Körper.", + "resource_path": "res://assets/icons/glutpakt/unit_g09_herdhueter_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g09_herdhueter_icon.png", + "record_path": "assets-source/phase3/records/g09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b1acc547c67290c157b4ef7f3c1a842d98aaca2a289330111086b1a0ec5271b8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "g10", + "display_name": "Sonnenesse", + "faction": "glutpakt", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Große Sonnenesse mit strahlender Ofenöffnung, Messingkrone und breiter wärmender Glutschale.", + "resource_path": "res://assets/icons/glutpakt/unit_g10_sonnenesse_icon.png", + "master_path": "assets-source/phase3/masters/glutpakt/unit_g10_sonnenesse_icon.png", + "record_path": "assets-source/phase3/records/g10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "8be9406f7a64af3016549c55392a868952f28a03470ad7caa1ae21bda17029ed", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m01", + "display_name": "Kesselwicht", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Kesseltank mit rundem Petrolkessel, Keramikgesicht und kurzen Stempelbeinen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m01_kesselwicht_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m01_kesselwicht_icon.png", + "record_path": "assets-source/phase3/records/m01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "805516bc05c0071d8127ad9620d5e0259d849a5d2d5a77211fb3384621eb2431", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m02", + "display_name": "Druckhüter", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter gepanzerter Drucktank mit Schulterkesseln und massivem Schildarm.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m02_druckhueter_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m02_druckhueter_icon.png", + "record_path": "assets-source/phase3/records/m02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c807ed0a7f27c0ab97747e9fa1677e4a634d55f60917ec00712f149f394406dc", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m03", + "display_name": "Scherschreiter", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schmaler Schreitautomat mit zwei großen Scherenarmen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m03_scherschreiter_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m03_scherschreiter_icon.png", + "record_path": "assets-source/phase3/records/m03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "a787b97d68846d18b4e026737e68ee99f7c76dadd0049891fedd9ae71c29c791", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m04", + "display_name": "Sechsklingler", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Schreitautomat mit sechs deutlich getrennten Klingen.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m04_sechsklingler_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m04_sechsklingler_icon.png", + "record_path": "assets-source/phase3/records/m04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "973e8288bc978d76e317a75710ee1d76f398286ba6c0c8dadf369601b64236ce", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m05", + "display_name": "Bolzenknecht", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Bolzenautomat mit einem deutlich lesbaren Armwerfer.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m05_bolzenknecht_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m05_bolzenknecht_icon.png", + "record_path": "assets-source/phase3/records/m05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "6e761bc1560e224b3f5960d956b95dae79d3edfd6a8a9c34aa9cb486d607e0ea", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m06", + "display_name": "Linienmeister", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Präzisionsautomat mit einer langen integrierten Balliste.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m06_linienmeister_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m06_linienmeister_icon.png", + "record_path": "assets-source/phase3/records/m06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "e20807102dc75df738b7d3b53dd49e2c9726895f53fbda5540f5b5fedb2164e2", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m07", + "display_name": "Klangkolben", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter Artillerieautomat mit einem großen Glockenrohr und Kolben.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m07_klangkolben_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m07_klangkolben_icon.png", + "record_path": "assets-source/phase3/records/m07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "91a12d9dfb9c7d7b2b32757443d5c6e591c974012a82002198de5f529694b180", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m08", + "display_name": "Resonanzramme", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Artillerieautomat mit zwei großen Resonanzkesseln.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m08_resonanzramme_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m08_resonanzramme_icon.png", + "record_path": "assets-source/phase3/records/m08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1e6966fd9f4d950abf2b8c841d2e9704b9685c38d99aecb7be16eb54f5848a57", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m09", + "display_name": "Taktspindel", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Taktgeber auf Spindelbeinen mit einem Dirigentenstab.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m09_taktspindel_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m09_taktspindel_icon.png", + "record_path": "assets-source/phase3/records/m09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "f4338c8a1e2625c2f607a9cf6663cfd590a9877afabce17d1c317356660b3109", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "m10", + "display_name": "Taktprälat", + "faction": "nietenkonvent", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Uhrwerkdirigent mit kronenförmigem Metronom und breitem Mantelkörper.", + "resource_path": "res://assets/icons/nietenkonvent/unit_m10_taktpraelat_icon.png", + "master_path": "assets-source/phase3/masters/nietenkonvent/unit_m10_taktpraelat_icon.png", + "record_path": "assets-source/phase3/records/m10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "5f11a0c174836e8a766b687bd962058caa4ec49979f59e1cafd9d28122c84302", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n01", + "display_name": "Saummaske", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter gefalteter Nebelkörper mit heller Ovalmaske, Sichelarmen und zwei Standranken.", + "resource_path": "res://assets/icons/nebelchor/unit_n01_saummaske_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n01_saummaske_icon.png", + "record_path": "assets-source/phase3/records/n01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "38be12140e3bfe7cab181c9a1ecda37c797d0358b67f856a33119cc2d0645a3a", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n02", + "display_name": "Grenzmaske", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Nebeltank mit heller Ovalmaske und mehreren geschichteten Sichelschilden.", + "resource_path": "res://assets/icons/nebelchor/unit_n02_grenzmaske_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n02_grenzmaske_icon.png", + "record_path": "assets-source/phase3/records/n02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "745ed920728e6450d307e3e1f6d4f8f9dd2a4aa758165cab8bce8f60de7a6ca8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n03", + "display_name": "Fadentänzer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker maskierter Nebeltänzer mit zwei versetzt geführten Fadenklingen und langen Standranken.", + "resource_path": "res://assets/icons/nebelchor/unit_n03_fadentaenzer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n03_fadentaenzer_icon.png", + "record_path": "assets-source/phase3/records/n03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "9d58b482e40ead9680778f4341ebc5153c645f42727618b83e9a6c188cbfbdd9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n04", + "display_name": "Saumzertrenner", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Nebelklingenkrieger mit Sichelkamm und großer geöffneter Sichelschere.", + "resource_path": "res://assets/icons/nebelchor/unit_n04_saumzertrenner_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n04_saumzertrenner_icon.png", + "record_path": "assets-source/phase3/records/n04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "3a2c80cb65eab5849515e19b19821fef2ea1f685f3d5b5f7c97fce038dea1886", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n05", + "display_name": "Fernflüsterer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schmale gefaltete Maskenfigur mit langem Flüsterhorn und mintfarbener Schallöffnung.", + "resource_path": "res://assets/icons/nebelchor/unit_n05_fernfluesterer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n05_fernfluesterer_icon.png", + "record_path": "assets-source/phase3/records/n05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "ca2e0494ddf5ca1bfb2247f77dca44eb565dcad481ff147c6815fba3449e7878", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n06", + "display_name": "Fernrufer", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Aufgewerteter Nebelrufer mit zwei weit geschwungenen Resonanzhörnern und mintfarbenen Schallöffnungen.", + "resource_path": "res://assets/icons/nebelchor/unit_n06_fernrufer_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n06_fernrufer_icon.png", + "record_path": "assets-source/phase3/records/n06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "4db796780eccf39a417fc5096295c96c561ba8de0502651879cf62f83a51767f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n07", + "display_name": "Glockenschlepper", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Nebelträger mit großer heller Glocke und deutlich sichtbarem mintfarbenem Klöppel.", + "resource_path": "res://assets/icons/nebelchor/unit_n07_glockenschlepper_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n07_glockenschlepper_icon.png", + "record_path": "assets-source/phase3/records/n07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d72a6247172ae48658e3f79b297a0e6b8eb2aed32c4fab317331595c9ff2c771", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n08", + "display_name": "Hohlgeläut", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher lebender Kathedralenglockenkörper mit drei Sichelspitzen und mintfarbenem Klöppel im offenen Brustraum.", + "resource_path": "res://assets/icons/nebelchor/unit_n08_hohlgelaeut_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n08_hohlgelaeut_icon.png", + "record_path": "assets-source/phase3/records/n08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "43485c1f6b7f55ea5b5eee34692d503aa1b1df0c6c1f4ebfd902ce9f16f86f22", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n09", + "display_name": "Maskenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kompakter maskierter Nebelsänger mit einer frei schwebenden Begleitmaske über dem erhobenen Sichelarm.", + "resource_path": "res://assets/icons/nebelchor/unit_n09_maskenkantor_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n09_maskenkantor_icon.png", + "record_path": "assets-source/phase3/records/n09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "f6d5c42d7f7cee21d82ccc5d72b31a9e45c0eb3ee6742dcb2efcbb5bfae15798", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "n10", + "display_name": "Vielstimmenkantor", + "faction": "nebelchor", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gekrönter Nebelchor-Kantor mit breitem Sichelkragen und drei getrennt schwebenden Begleitmasken.", + "resource_path": "res://assets/icons/nebelchor/unit_n10_vielstimmenkantor_icon.png", + "master_path": "assets-source/phase3/masters/nebelchor/unit_n10_vielstimmenkantor_icon.png", + "record_path": "assets-source/phase3/records/n10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "18519abaa51aa463ebf4b7800d9c75742550d897fe30d77772cbb64f7860a0fd", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w01", + "display_name": "Dornhopser", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleine hüpfende Dornkapsel auf breiten Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w01_dornhopser_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w01_dornhopser_icon.png", + "record_path": "assets-source/phase3/records/w01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b20324131147bd27b0514f05fbbc9d763afb0bbc1185fe4578bc2f97ec3304a1", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w02", + "display_name": "Rankenschnapper", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breiter Rankenräuber mit großem Dornenmaul und Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w02_rankenschnapper_icon.png", + "record_path": "assets-source/phase3/records/w02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b9cabce9916cf9821a93698b88b000d4dca25e9138eeca28385fdaaed4f357e4", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w03", + "display_name": "Korkrücken", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener Tank mit breitem Korkpanzer, Moos und Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w03_korkruecken_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w03_korkruecken_icon.png", + "record_path": "assets-source/phase3/records/w03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "bf7ec6d9700c6b59d14953eb62aee48f6c2bb4d7180d9820ff75abb09e56e807", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w04", + "display_name": "Ringborke", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Wurzeltank mit konzentrischen Holzringen als massiver Panzerung.", + "resource_path": "res://assets/icons/wurzelbund/unit_w04_ringborke_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w04_ringborke_icon.png", + "record_path": "assets-source/phase3/records/w04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b2681145788f69c0211444c022258c819e1eb268fb2f4ca27be39dacbbdf5151", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w05", + "display_name": "Samenschleuder", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker Wurzelfernkämpfer mit gebogener Ranke und offener Samenkapsel als Wurfschale.", + "resource_path": "res://assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w05_samenschleuder_icon.png", + "record_path": "assets-source/phase3/records/w05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "6b2b8da08701cea3172c9d9fb491ed8ef19d68b5e19969eca0ecdf4c198f5a9f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w06", + "display_name": "Zapfenkrone", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hoher Samenschütze mit großer Zapfenkrone, kräftigen Ranken und Blattschalen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w06_zapfenkrone_icon.png", + "record_path": "assets-source/phase3/records/w06.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7806055424d77d0cbf339e7ca7c316c597a5725553e01b1df163e54bb1bfe166", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w07", + "display_name": "Sporenkelch", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Niedriger offener Pilzkelch mit rosiger Sporenmulde und breiten Wurzelfüßen.", + "resource_path": "res://assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w07_sporenkelch_icon.png", + "record_path": "assets-source/phase3/records/w07.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d696f2e7161c46c032c46913173be1e35747d729bb30ec931f891fe0a6f911ee", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w08", + "display_name": "Pilzkathedrale", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Große mobile Pilzarchitektur mit gestaffelten rosigen Pilzdächern und massivem Wurzelwerk.", + "resource_path": "res://assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w08_pilzkathedrale_icon.png", + "record_path": "assets-source/phase3/records/w08.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "5de336a54520876f5b9647fcf8158a42074a3c799be9fc554a79a50e6f806ce0", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w09", + "display_name": "Tauhüter", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleiner Blatthüter mit einzelnem Tautropfen in einer schützenden Blattschale.", + "resource_path": "res://assets/icons/wurzelbund/unit_w09_tauhueter_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w09_tauhueter_icon.png", + "record_path": "assets-source/phase3/records/w09.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b3fae10448ee3128e1e7d636ede427fd8477bb6080f67711e71aba5f467e2738", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "w10", + "display_name": "Quellgeflecht", + "faction": "wurzelbund", + "kind": "unit_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Großer Heiler aus verflochtenen Wurzeln mit Quellwasserschale unter einem Blüten- und Blätterdach.", + "resource_path": "res://assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png", + "master_path": "assets-source/phase3/masters/wurzelbund/unit_w10_quellgeflecht_icon.png", + "record_path": "assets-source/phase3/records/w10.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "69f386bf084e7d48d293195039d57c0284c3809fc5781b72e7b79af3beec2e93", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s01", + "display_name": "Nadelspäher", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schlanker maskierter Söldnerspäher mit kompaktem Nadelwerfer.", + "resource_path": "res://assets/icons/neutral/unit_s01_nadelspaeher_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s01_nadelspaeher_icon.png", + "record_path": "assets-source/phase3/records/s01.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "e90a5e0d9d651a4f4bd6ce95684bc4e7badb000abef719be69809f889c57ac03", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s02", + "display_name": "Rostschieber", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Gedrungener schwerer Söldner mit Rostpanzer und großem Rammschild.", + "resource_path": "res://assets/icons/neutral/unit_s02_rostschieber_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s02_rostschieber_icon.png", + "record_path": "assets-source/phase3/records/s02.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "295e2ee585816b0cfe3410aa2b5fcf92879d49cb4674d590cb0e50f2d861002d", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s03", + "display_name": "Dunstsänger", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Verhüllter violetter Dunstsänger mit großem Resonanzhorn.", + "resource_path": "res://assets/icons/neutral/unit_s03_dunstsaenger_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s03_dunstsaenger_icon.png", + "record_path": "assets-source/phase3/records/s03.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "a3c0a2df180025d7e0afaab410c70d348f740feab1a45603ba9bf6a7fd8713c2", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s04", + "display_name": "Keilbrecher", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Schwerer dunkelgrauer Keilbrecher mit großem Keilhammer.", + "resource_path": "res://assets/icons/neutral/unit_s04_keilbrecher_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s04_keilbrecher_icon.png", + "record_path": "assets-source/phase3/records/s04.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "bd13a44d2f497a16eaabce31607cfbed9fa1f068bff2fa50e4643a95f6575b45", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "s05", + "display_name": "Risszehrer", + "faction": "neutral", + "kind": "mercenary_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hohler Risszehrer mit mintviolettem Schlund und magischer Entzugskugel.", + "resource_path": "res://assets/icons/neutral/unit_s05_risszehrer_icon.png", + "master_path": "assets-source/phase3/masters/neutral/unit_s05_risszehrer_icon.png", + "record_path": "assets-source/phase3/records/s05.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c026f680dbf8c4979334bf05f475fc9e231247f6d68997a72d560133ed113bd9", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_gold", + "display_name": "Gold", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Eine große facettierte Goldmünze mit zwei kleineren Münzen.", + "resource_path": "res://assets/icons/resources/res_gold.png", + "master_path": "assets-source/phase3/masters/resources/res_gold.png", + "record_path": "assets-source/phase3/records/res_gold.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "c35163d614af2d20dd985ebcdd88c5a7aeb242a55f2b60fe0d3760dc8a175802", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_sparks", + "display_name": "Funken", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleines Messing-Glasgefäß mit leuchtender mintfarbener Funkenenergie.", + "resource_path": "res://assets/icons/resources/res_sparks.png", + "master_path": "assets-source/phase3/masters/resources/res_sparks.png", + "record_path": "assets-source/phase3/records/res_sparks.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d6a8a3d6518837d81455b4e64c67543112d0cb545479780d8af4827ad6f59b68", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_income", + "display_name": "Einkommen", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Messingsiegel mit drei von links nach rechts ansteigenden Münzstapeln.", + "resource_path": "res://assets/icons/resources/res_income.png", + "master_path": "assets-source/phase3/masters/resources/res_income.png", + "record_path": "assets-source/phase3/records/res_income.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "34877b2ffbd402273329137beaaa145e540ee9a06b94593b827f402de52bf163", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "res_core", + "display_name": "Kernleben", + "faction": "resources", + "kind": "resource_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Korallfarbenes facettiertes Kristallherz in einer kleinen Messingfassung.", + "resource_path": "res://assets/icons/resources/res_core.png", + "master_path": "assets-source/phase3/masters/resources/res_core.png", + "record_path": "assets-source/phase3/records/res_core.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "b545deb38c922e26ef3b99bd976fa69d5622723c3847d2bd474d40162f4aa931", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "worker_funkenleser", + "display_name": "Funkenleser", + "faction": "neutral", + "kind": "worker_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Kleine Lehmgestalt im Arbeitstuch mit gegabeltem Funkensammler und Glasbehälter.", + "resource_path": "res://assets/icons/neutral/worker_funkenleser_icon.png", + "master_path": "assets-source/phase3/masters/neutral/worker_funkenleser_icon.png", + "record_path": "assets-source/phase3/records/worker_funkenleser.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "af4de34df59225e3d5f6a2f167227303978a3ccf4cac2208d74962013b517d12", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_blade", + "display_name": "Klinge", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Einzelne gebogene Elfenbeinklinge mit Messingparierstange und Graphitgriff.", + "resource_path": "res://assets/icons/types/type_damage_blade.png", + "master_path": "assets-source/phase3/masters/types/type_damage_blade.png", + "record_path": "assets-source/phase3/records/type_damage_blade.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "d8166abd9bd9e8e68ef26debcf710c6e601d7d5afc73be27f5f09283892c867f", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_pierce", + "display_name": "Durchschlag", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Lange Messingpfeilspitze durchstößt eine kleine graphitfarbene Rautenplatte.", + "resource_path": "res://assets/icons/types/type_damage_pierce.png", + "master_path": "assets-source/phase3/masters/types/type_damage_pierce.png", + "record_path": "assets-source/phase3/records/type_damage_pierce.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1d2d9b55d5da3be849194485e212a585393c7d69fa3a690dff1297e89b9884c0", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_damage_pulse", + "display_name": "Impuls", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Mintfarbener facettierter Sternkern zwischen zwei offenen graphitfarbenen Ringhälften.", + "resource_path": "res://assets/icons/types/type_damage_pulse.png", + "master_path": "assets-source/phase3/masters/types/type_damage_pulse.png", + "record_path": "assets-source/phase3/records/type_damage_pulse.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "9d0c1807fcd16f3e01e53d33fd76f53f5815aa81e1aba9c43c8fe03e708541db", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_light", + "display_name": "Leichte Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Dünne blattförmige Lederpanzerplatte in warmem Ocker mit einfachem Graphitriemen.", + "resource_path": "res://assets/icons/types/type_armor_light.png", + "master_path": "assets-source/phase3/masters/types/type_armor_light.png", + "record_path": "assets-source/phase3/records/type_armor_light.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "1a1bf7bb9ad703270ccd30fa4ea3e72f3f9139ff65198922183d8f5278f59d36", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_heavy", + "display_name": "Schwere Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Breite schwere Schildplatte aus drei Graphitstahllagen mit hellen Kanten und Messingverstärkung.", + "resource_path": "res://assets/icons/types/type_armor_heavy.png", + "master_path": "assets-source/phase3/masters/types/type_armor_heavy.png", + "record_path": "assets-source/phase3/records/type_armor_heavy.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "ff1c430ec625abe969ae10b874cf8ee0c23ace39a881d84d336e1b6fb234a9c8", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "type_armor_aether", + "display_name": "Ätherische Rüstung", + "faction": "types", + "kind": "type_icon", + "import_size_limit": 256, + "requires_alpha": true, + "description_de": "Hohler violetter Geisterschild mit mintfarbener Innenkante und transparentem Innenraum.", + "resource_path": "res://assets/icons/types/type_armor_aether.png", + "master_path": "assets-source/phase3/masters/types/type_armor_aether.png", + "record_path": "assets-source/phase3/records/type_armor_aether.json", + "width": 1254, + "height": 1254, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "7f9ffc611e252007a468e472bb9c9e4a2d95ba928624d54e1b0e5868174a9d4b", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "map_overview", + "display_name": "Doppelsteg – Kartenkonzept", + "faction": "map", + "kind": "map_concept", + "import_size_limit": 0, + "requires_alpha": false, + "description_de": "Zwei parallele Felsstege über einer Schlucht, mit nördlichen Aufmarschflächen, mittleren Baufeldern und südlichen Kernplattformen in Türkis und Koralle.", + "resource_path": "res://assets/concepts/map_overview.png", + "master_path": "assets-source/phase3/masters/map/map_overview.png", + "record_path": "assets-source/phase3/records/map_overview.json", + "width": 1374, + "height": 1145, + "mode": "RGB", + "alpha_range": null, + "sha256": "4120e7dc3c56c9f27fe81acbb2fd47911458b067a9c3b9d26d3800cecde364c7", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "map_lane_floor", + "display_name": "Baufeld-Bodenkachel", + "faction": "map", + "kind": "tile_concept", + "import_size_limit": 0, + "requires_alpha": false, + "description_de": "Flache quadratische Steinplatte mit großen ruhigen Flächen und schmalen Moosfugen für das Baufeld.", + "resource_path": "res://assets/concepts/map_lane_floor.png", + "master_path": "assets-source/phase3/masters/map/map_lane_floor.png", + "record_path": "assets-source/phase3/records/map_lane_floor.json", + "width": 1254, + "height": 1254, + "mode": "RGB", + "alpha_range": null, + "sha256": "1e0984c6309ee95e7557aa6e7d6d823ac7b40d0a9651c5479d6f98f0dc297758", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "map_lane_edge", + "display_name": "Lane-Randkachel", + "faction": "map", + "kind": "tile_concept", + "import_size_limit": 0, + "requires_alpha": false, + "description_de": "Passende Randplatte mit niedriger äußerer Steinbrüstung und kleinem Messingmarker.", + "resource_path": "res://assets/concepts/map_lane_edge.png", + "master_path": "assets-source/phase3/masters/map/map_lane_edge.png", + "record_path": "assets-source/phase3/records/map_lane_edge.json", + "width": 1254, + "height": 1254, + "mode": "RGB", + "alpha_range": null, + "sha256": "81727f5e0374a20df23687485dbf705cad5ba62b1776ae330c0a090d5d6ed309", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "map_leak_line", + "display_name": "Lecklinie-Kachel", + "faction": "map", + "kind": "tile_concept", + "import_size_limit": 0, + "requires_alpha": false, + "description_de": "Steinplatte mit durchgehendem mintfarbenem Lichtstreifen in einer schmalen Messingschiene als Lecklinie.", + "resource_path": "res://assets/concepts/map_leak_line.png", + "master_path": "assets-source/phase3/masters/map/map_leak_line.png", + "record_path": "assets-source/phase3/records/map_leak_line.json", + "width": 1254, + "height": 1254, + "mode": "RGB", + "alpha_range": null, + "sha256": "6198a42b5d2d5a4249ff779c8a2243fecbfcd16b424e598f6c43c055b176b648", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_panel_a", + "display_name": "Breiter UI-Rahmen", + "faction": "ui", + "kind": "ui_frame", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Breiter offener UI-Rahmen mit Basaltfassung, schmaler Messingkante und ruhigen, geraden Seiten.", + "resource_path": "res://assets/ui/ui_panel_a.png", + "master_path": "assets-source/phase3/masters/ui/ui_panel_a.png", + "record_path": "assets-source/phase3/records/ui_panel_a.json", + "width": 2172, + "height": 724, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "65905847cba0899faf6ea91fae7218f3b69066821fe3431727ecda8094314556", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_panel_b", + "display_name": "Hoher UI-Rahmen", + "faction": "ui", + "kind": "ui_frame", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Hoher offener UI-Rahmen für Einheiteninfos, mit Basaltfassung und geometrischen Messingecken.", + "resource_path": "res://assets/ui/ui_panel_b.png", + "master_path": "assets-source/phase3/masters/ui/ui_panel_b.png", + "record_path": "assets-source/phase3/records/ui_panel_b.json", + "width": 1024, + "height": 1536, + "mode": "RGBA", + "alpha_range": [ + 0, + 254 + ], + "sha256": "67440e840cc235ea8aea0052ea656f6b33d87eb7fce6b4ce4862a7bd1df4e73e", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_button_normal", + "display_name": "Button – Normal", + "faction": "ui", + "kind": "ui_button", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Unbeschrifteter petrolfarbener Button mit kantigem Messingrand, dunkler Innenfläche und kleinen geometrischen Eckakzenten.", + "resource_path": "res://assets/ui/ui_button_normal.png", + "master_path": "assets-source/phase3/masters/ui/ui_button_normal.png", + "record_path": "assets-source/phase3/records/ui_button_normal.json", + "width": 2172, + "height": 724, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "afddec4527e64a0c12fbefe3ec645e124cb743fb517c4fa650d9ce73718052df", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_button_hover", + "display_name": "Button – Hover", + "faction": "ui", + "kind": "ui_button", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Hover-Zustand mit hellerem Messingrand und einer schmalen mintfarbenen Innenkante.", + "resource_path": "res://assets/ui/ui_button_hover.png", + "master_path": "assets-source/phase3/masters/ui/ui_button_hover.png", + "record_path": "assets-source/phase3/records/ui_button_hover.json", + "width": 2172, + "height": 724, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "86ee851ca9c887eceeaccb918c018a1ab4833bec1442389201f27ef3b7e93255", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_button_pressed", + "display_name": "Button – Gedrückt", + "faction": "ui", + "kind": "ui_button", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Gedrückter Button mit abgedunkelter, eingesenkter Petrolfläche und umgekehrtem Innenrelief.", + "resource_path": "res://assets/ui/ui_button_pressed.png", + "master_path": "assets-source/phase3/masters/ui/ui_button_pressed.png", + "record_path": "assets-source/phase3/records/ui_button_pressed.json", + "width": 2172, + "height": 724, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "9010889c33a9db089ff7d697d328caedbec75dbc42600ab7efc69b9d005b99da", + "generation_mode": "built-in", + "status": "prepared" + }, + { + "id": "ui_button_disabled", + "display_name": "Button – Deaktiviert", + "faction": "ui", + "kind": "ui_button", + "import_size_limit": 0, + "requires_alpha": true, + "description_de": "Deaktivierter Button in entsättigtem Schiefergrau und gedämpftem Messing.", + "resource_path": "res://assets/ui/ui_button_disabled.png", + "master_path": "assets-source/phase3/masters/ui/ui_button_disabled.png", + "record_path": "assets-source/phase3/records/ui_button_disabled.json", + "width": 2172, + "height": 724, + "mode": "RGBA", + "alpha_range": [ + 0, + 255 + ], + "sha256": "57f41d364e35f223e3892eb33ff0d92fe9c4c38cd588142347cb14c073f30274", + "generation_mode": "built-in", + "status": "prepared" + } + ] +} diff --git a/assets/phase4_manifest.json b/assets/phase4_manifest.json new file mode 100644 index 0000000..f1b6281 --- /dev/null +++ b/assets/phase4_manifest.json @@ -0,0 +1,9853 @@ +{ + "phase": 4, + "asset_count": 59, + "blender_version": "5.2.1 LTS", + "coordinate_system": "Metres; glTF/Godot +Y up, +Z forward; ground origin. Lane top at Y=0.", + "assets": [ + { + "id": "g01", + "name": "Kohlenbeißer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g01.blend", + "triangles": 79780, + "mesh_parts": 131, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_JawCavity", + "Head_MouthEmber", + "Head_BrowL", + "Head_EyeL", + "Head_CheekL", + "Head_UpperToothL0", + "Head_LowerToothL0", + "Head_UpperToothL1", + "Head_LowerToothL1", + "Head_UpperToothL2", + "Head_LowerToothL2", + "Head_UpperToothL3", + "Head_LowerToothL3", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "WeaponL_Claw0", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle0_Head", + "WeaponL_Claw1", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle1_Head", + "WeaponL_Claw2", + "ArmL_Knuckle2_Seat", + "ArmL_Knuckle2_Head", + "ArmL_ShoulderTrim", + "Head_BrowR", + "Head_EyeR", + "Head_CheekR", + "Head_UpperToothR0", + "Head_LowerToothR0", + "Head_UpperToothR1", + "Head_LowerToothR1", + "Head_UpperToothR2", + "Head_LowerToothR2", + "Head_UpperToothR3", + "Head_LowerToothR3", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "WeaponR_Claw0", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle0_Head", + "WeaponR_Claw1", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle1_Head", + "WeaponR_Claw2", + "ArmR_Knuckle2_Seat", + "ArmR_Knuckle2_Head", + "ArmR_ShoulderTrim", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Head_Chin" + ], + "bounds_blender": { + "min": [ + -0.7924438118934631, + -0.4473014771938324, + 0.0 + ], + "max": [ + 0.7924438118934631, + 0.44730144739151, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.7924438118934631, + 0.0, + -0.44730144739151 + ], + "max": [ + 0.7924438118934631, + 1.350000023841858, + 0.4473014771938324 + ] + }, + "scale_applied": 0.9629486449307071, + "blender_version": "5.2.1 LTS", + "sha256": "b51f8bb5188c950f4f9cecde7125b225d7ba5cbe103d89335047dd97a2873c1d", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 641050 + }, + { + "id": "g02", + "name": "Schlackenklaue", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g02.blend", + "triangles": 75624, + "mesh_parts": 133, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_JawCavity", + "Head_MouthEmber", + "Head_BrowL", + "Head_EyeL", + "Head_CheekL", + "Head_UpperToothL0", + "Head_LowerToothL0", + "Head_UpperToothL1", + "Head_LowerToothL1", + "Head_UpperToothL2", + "Head_LowerToothL2", + "Head_UpperToothL3", + "Head_LowerToothL3", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "WeaponL_Claw0", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle0_Head", + "WeaponL_Claw1", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle1_Head", + "WeaponL_Claw2", + "ArmL_Knuckle2_Seat", + "ArmL_Knuckle2_Head", + "ArmL_ShoulderTrim", + "Head_BrowR", + "Head_EyeR", + "Head_CheekR", + "Head_UpperToothR0", + "Head_LowerToothR0", + "Head_UpperToothR1", + "Head_LowerToothR1", + "Head_UpperToothR2", + "Head_LowerToothR2", + "Head_UpperToothR3", + "Head_LowerToothR3", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "WeaponR_Claw0", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle0_Head", + "WeaponR_Claw1", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle1_Head", + "WeaponR_Claw2", + "ArmR_Knuckle2_Seat", + "ArmR_Knuckle2_Head", + "ArmR_ShoulderTrim", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Head_Chin" + ], + "bounds_blender": { + "min": [ + -0.8933426141738892, + -0.48825082182884216, + 0.0 + ], + "max": [ + 0.8933426141738892, + 0.4882507920265198, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.8933426141738892, + 0.0, + -0.4882507920265198 + ], + "max": [ + 0.8933426141738892, + 1.5, + 0.48825082182884216 + ] + }, + "scale_applied": 1.0511041683008056, + "blender_version": "5.2.1 LTS", + "sha256": "b008047744d5e82ed47ca50a61ca633fd38599446669079be9677b020e411486", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 549234 + }, + { + "id": "g03", + "name": "Schlackenwacht", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g03.blend", + "triangles": 67232, + "mesh_parts": 119, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold" + ], + "bounds_blender": { + "min": [ + -0.8888235092163086, + -0.43674787878990173, + 0.0 + ], + "max": [ + 0.8888235092163086, + 0.4367479383945465, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.8888235092163086, + 0.0, + -0.4367479383945465 + ], + "max": [ + 0.8888235092163086, + 1.350000023841858, + 0.43674787878990173 + ] + }, + "scale_applied": 1.0527888124172442, + "blender_version": "5.2.1 LTS", + "sha256": "4a6e16b9ecd40f3ab9176c0fbe37cc52c27b9da16406732daa1587e37e135fa0", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 565982 + }, + { + "id": "g04", + "name": "Basaltbastion", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g04.blend", + "triangles": 80764, + "mesh_parts": 220, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowRecess2", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_Merlon0", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap3", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowRecess2", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_Merlon0", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap3", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold", + "Head_Crown_StoneKeep", + "Head_Crown_LowerCornice", + "Head_Crown_UpperCornice", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowFire0", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowFire1", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowRecess2", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel2", + "Head_Crown_Merlon0", + "Head_Crown_MerlonCap0", + "Head_Crown_Merlon1", + "Head_Crown_MerlonCap1", + "Head_Crown_Merlon2", + "Head_Crown_MerlonCap2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap3", + "Body_SpineGold" + ], + "bounds_blender": { + "min": [ + -0.7569541335105896, + -0.37195026874542236, + 0.0 + ], + "max": [ + 0.7569541335105896, + 0.37195026874542236, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.7569541335105896, + 0.0, + -0.37195026874542236 + ], + "max": [ + 0.7569541335105896, + 1.5, + 0.37195026874542236 + ] + }, + "scale_applied": 0.8965928946707251, + "blender_version": "5.2.1 LTS", + "sha256": "9f9a963c80b3b79817eee4ea9e75af3819ca1a204e17d9bdb0072f3b5f60ab7c", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 470044 + }, + { + "id": "g05", + "name": "Funkenlanze", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_g05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g05.blend", + "triangles": 54710, + "mesh_parts": 118, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_ShinGold", + "LegL_ShinEmber", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_ShinGold", + "LegR_ShinEmber", + "Body_Spine", + "Body_CuirassL", + "Body_ChestStoneL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_ShoulderFin", + "Body_CuirassR", + "Body_ChestStoneR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_ShoulderFin", + "Body_EmberHeart", + "Head_Neck", + "Head_Helmet", + "Head_Visor", + "Head_Crest", + "Weapon_LanceShaft", + "Weapon_LanceEmber", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceCollar10", + "Weapon_SpearHead", + "Weapon_SpearEdge_1", + "Weapon_SpearEdge1" + ], + "bounds_blender": { + "min": [ + -0.7841845750808716, + -0.22315844893455505, + 0.0 + ], + "max": [ + 0.7841845750808716, + 0.22315844893455505, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.7841845750808716, + 0.0, + -0.22315844893455505 + ], + "max": [ + 0.7841845750808716, + 1.4500000476837158, + 0.22315844893455505 + ] + }, + "scale_applied": 0.8333333287659276, + "blender_version": "5.2.1 LTS", + "sha256": "f21ee9e96ae65f986a6f51ce950ec1885bb7da7f72f58e232f37d9255ca3e49a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 382610 + }, + { + "id": "g06", + "name": "Glasballiste", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_g06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g06.blend", + "triangles": 38036, + "mesh_parts": 85, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_Gearbox", + "Body_CrankL", + "Body_CrankInsetL", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Weapon_RailL", + "Weapon_RailTrimL", + "Weapon_GlassLimbL", + "Weapon_LimbEdgeL", + "Weapon_DrawCableL", + "Weapon_LimbClampL", + "Body_CrankR", + "Body_CrankInsetR", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Weapon_RailR", + "Weapon_RailTrimR", + "Weapon_GlassLimbR", + "Weapon_LimbEdgeR", + "Weapon_DrawCableR", + "Weapon_LimbClampR", + "Weapon_RearHousing", + "Weapon_RearTrim", + "Weapon_CentralBolt", + "Weapon_BoltHead", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5" + ], + "bounds_blender": { + "min": [ + -0.9249999523162842, + -0.8653658628463745, + 0.0 + ], + "max": [ + 0.9249999523162842, + 0.8653659224510193, + 1.3369946479797363 + ] + }, + "bounds_godot": { + "min": [ + -0.9249999523162842, + 0.0, + -0.8653659224510193 + ], + "max": [ + 0.9249999523162842, + 1.3369946479797363, + 0.8653658628463745 + ] + }, + "scale_applied": 1.0914242850007518, + "blender_version": "5.2.1 LTS", + "sha256": "6480508f062b8610cfbcc24b0067d25a80b7404de29a12c49a99fd6b5a379cee", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 261386 + }, + { + "id": "g07", + "name": "Aschenwerfer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_g07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g07.blend", + "triangles": 81492, + "mesh_parts": 128, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LowerCore", + "Body_MortarBore", + "Body_MortarStave0", + "Body_RimClasp0", + "Body_MortarStave1", + "Body_RimClasp1", + "Body_MortarStave2", + "Body_RimClasp2", + "Body_MortarStave3", + "Body_RimClasp3", + "Body_MortarStave4", + "Body_RimClasp4", + "Body_MortarStave5", + "Body_RimClasp5", + "Body_MortarStave6", + "Body_RimClasp6", + "Body_MortarStave7", + "Body_RimClasp7", + "Body_MortarStave8", + "Body_RimClasp8", + "Body_MortarStave9", + "Body_RimClasp9", + "Body_MortarStave10", + "Body_RimClasp10", + "Body_MortarStave11", + "Body_RimClasp11", + "Body_MortarLip", + "Body_MortarBelt", + "Weapon_LavaPool", + "Weapon_EmberBoulder", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil" + ], + "bounds_blender": { + "min": [ + -0.821897029876709, + -0.6239631772041321, + 0.0 + ], + "max": [ + 0.8218969702720642, + 0.6239631772041321, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.821897029876709, + 0.0, + -0.6239631772041321 + ], + "max": [ + 0.8218969702720642, + 1.350000023841858, + 0.6239631772041321 + ] + }, + "scale_applied": 1.136363671028108, + "blender_version": "5.2.1 LTS", + "sha256": "e8112a137032ca74e5d50714f49ee3a318e37e3323572ed6d5d153a38c726a88", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 687762 + }, + { + "id": "g08", + "name": "Kraterrufer", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_g08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g08.blend", + "triangles": 77130, + "mesh_parts": 123, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_LowerCore", + "Body_MortarBore", + "Body_MortarStave0", + "Body_RimClasp0", + "Body_MortarStave1", + "Body_RimClasp1", + "Body_MortarStave2", + "Body_RimClasp2", + "Body_MortarStave3", + "Body_RimClasp3", + "Body_MortarStave4", + "Body_RimClasp4", + "Body_MortarStave5", + "Body_RimClasp5", + "Body_MortarStave6", + "Body_RimClasp6", + "Body_MortarStave7", + "Body_RimClasp7", + "Body_MortarStave8", + "Body_RimClasp8", + "Body_MortarStave9", + "Body_RimClasp9", + "Body_MortarStave10", + "Body_RimClasp10", + "Body_MortarStave11", + "Body_RimClasp11", + "Body_MortarLip", + "Body_MortarBelt", + "Weapon_LavaPool", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil" + ], + "bounds_blender": { + "min": [ + -0.9132189750671387, + -0.745126485824585, + 0.0 + ], + "max": [ + 0.9132189154624939, + 0.745126485824585, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.9132189750671387, + 0.0, + -0.745126485824585 + ], + "max": [ + 0.9132189154624939, + 1.5, + 0.745126485824585 + ] + }, + "scale_applied": 1.2626263011423422, + "blender_version": "5.2.1 LTS", + "sha256": "1f7a3c940c5798ee73c7f2c2b91fbf2531f5446b85d0d3bd6f4554b6a0124cb6", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 683400 + }, + { + "id": "g09", + "name": "Herdhüter", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_g09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g09.blend", + "triangles": 84568, + "mesh_parts": 173, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_HearthBack", + "Body_OvenDark", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_ArchStone10", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Head_Chimney", + "Head_ChimneyRecess", + "Head_ChimneyCap", + "Weapon_HearthBowl", + "Weapon_BowlRim", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11" + ], + "bounds_blender": { + "min": [ + -0.6256327033042908, + -0.5413227677345276, + 0.0 + ], + "max": [ + 0.6256327033042908, + 0.5413227081298828, + 1.4500001668930054 + ] + }, + "bounds_godot": { + "min": [ + -0.6256327033042908, + 0.0, + -0.5413227081298828 + ], + "max": [ + 0.6256327033042908, + 1.4500001668930054, + 0.5413227677345276 + ] + }, + "scale_applied": 0.9206349624437739, + "blender_version": "5.2.1 LTS", + "sha256": "0b65843813708495ea96349bc5dab83c932e389f47327ef1892b7fb4e9481f97", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 685558 + }, + { + "id": "g10", + "name": "Sonnenesse", + "faction": "glutpakt", + "palette": "glutpakt", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_g10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_g10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/g10.blend", + "triangles": 96706, + "mesh_parts": 223, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_HearthBack", + "Body_OvenDark", + "Body_SunSocket", + "Body_SunFrame", + "Body_SunHeart", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_MantleL", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_TabardL", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_MantleR", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_TabardR", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Weapon_HearthBowl", + "Weapon_BowlRim", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Body_SolarStream" + ], + "bounds_blender": { + "min": [ + -0.6629917025566101, + -0.58647620677948, + 0.0 + ], + "max": [ + 0.6629916429519653, + 0.5864762663841248, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.6629917025566101, + 0.0, + -0.5864762663841248 + ], + "max": [ + 0.6629916429519653, + 1.600000023841858, + 0.58647620677948 + ] + }, + "scale_applied": 0.9756097646074449, + "blender_version": "5.2.1 LTS", + "sha256": "ed5a7c265e25d592a367b3bc8a152ee6ace6aabb2964b6f563b4509967829715", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 697696 + }, + { + "id": "m01", + "name": "Kesselwicht", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m01.glb", + "resource_path": "res://assets/models/unit_m01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m01.blend", + "triangles": 1284, + "mesh_parts": 42, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_RoundKettle", + "Body_Belt", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye_1", + "Head_Eye1", + "Head_Mouth", + "Body_PressureGauge", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_Chimney", + "Body_ChimneyLip", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Fist", + "ArmL_Cuff", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Fist", + "ArmR_Cuff" + ], + "bounds_blender": { + "min": [ + -0.5699462890625, + -0.3646690249443054, + 0.0 + ], + "max": [ + 0.5699462890625, + 0.3646690249443054, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.5699462890625, + 0.0, + -0.3646690249443054 + ], + "max": [ + 0.5699462890625, + 1.350000023841858, + 0.3646690249443054 + ] + }, + "scale_applied": 0.966010707083804, + "blender_version": "5.2.1 LTS", + "sha256": "dfa98866025c5801cc6aff2ef8273dfe393a397623f641046c4babade8516df1", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m02", + "name": "Druckhüter", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m02.glb", + "resource_path": "res://assets/models/unit_m02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m02.blend", + "triangles": 1360, + "mesh_parts": 52, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_HeavyChest", + "Body_CeramicChest_Rim", + "Body_CeramicChest_Face", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_PressureTankL", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_ValveStemL", + "Body_ValveWheelL", + "Body_PressureTankR", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemR", + "Body_ValveWheelR", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Fist", + "ArmL_Cuff", + "ArmL_Pauldron", + "ArmL_Shield_Rim", + "ArmL_Shield_Face", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Fist", + "ArmR_Cuff", + "ArmR_Pauldron", + "ArmR_Shield_Rim", + "ArmR_Shield_Face" + ], + "bounds_blender": { + "min": [ + -0.6054872274398804, + -0.2990065813064575, + 0.0 + ], + "max": [ + 0.6054872274398804, + 0.2990066111087799, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.6054872274398804, + 0.0, + -0.2990066111087799 + ], + "max": [ + 0.6054872274398804, + 1.5, + 0.2990065813064575 + ] + }, + "scale_applied": 0.9460737926177909, + "blender_version": "5.2.1 LTS", + "sha256": "8aeb014358b502dccdf0a8202214b8456e43e04c38333c6218eb7cbb0864bb2b", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m03", + "name": "Scherschreiter", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m03.glb", + "resource_path": "res://assets/models/unit_m03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m03.blend", + "triangles": 932, + "mesh_parts": 43, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "ArmL0_Rod", + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "ArmR0_Rod", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ], + "bounds_blender": { + "min": [ + -0.7748520374298096, + -0.14178994297981262, + 0.0 + ], + "max": [ + 0.7748520374298096, + 0.14178994297981262, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.7748520374298096, + 0.0, + -0.14178994297981262 + ], + "max": [ + 0.7748520374298096, + 1.350000023841858, + 0.14178994297981262 + ] + }, + "scale_applied": 0.7988165410007994, + "blender_version": "5.2.1 LTS", + "sha256": "8efdd35dfe2c6194f7b9705a0324d66ff260d9936f9099b6b1f81790c03831af", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m04", + "name": "Sechsklingler", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m04.glb", + "resource_path": "res://assets/models/unit_m04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m04.blend", + "triangles": 1398, + "mesh_parts": 60, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "ArmL0_Rod", + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "WeaponL0_Blade0", + "ArmL1_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "WeaponL1_Blade0", + "ArmL2_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "WeaponL2_Blade0", + "ArmR0_Rod", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "WeaponR0_Blade0", + "ArmR1_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "WeaponR1_Blade0", + "ArmR2_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "WeaponR2_Blade0" + ], + "bounds_blender": { + "min": [ + -0.821377158164978, + -0.15030355751514435, + 0.0 + ], + "max": [ + 0.821377158164978, + 0.15030354261398315, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.821377158164978, + 0.0, + -0.15030354261398315 + ], + "max": [ + 0.821377158164978, + 1.5, + 0.15030355751514435 + ] + }, + "scale_applied": 0.8467805123236263, + "blender_version": "5.2.1 LTS", + "sha256": "a55e114218bee93ee40dc90a368414bef0fae6d4580f032f72687565ec9d9bc8", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m05", + "name": "Bolzenknecht", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_m05.glb", + "resource_path": "res://assets/models/unit_m05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m05.blend", + "triangles": 1148, + "mesh_parts": 52, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "Head_Scope", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_String_1", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1" + ], + "bounds_blender": { + "min": [ + -0.3836592435836792, + -0.40458109974861145, + 0.0 + ], + "max": [ + 0.3836592435836792, + 0.40458106994628906, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.3836592435836792, + 0.0, + -0.40458106994628906 + ], + "max": [ + 0.3836592435836792, + 1.4499999284744263, + 0.40458109974861145 + ] + }, + "scale_applied": 0.8479531974579839, + "blender_version": "5.2.1 LTS", + "sha256": "0d5f61b02d29d09c807a6d6c07341620a4f1a4bee0d300391cbd4a9a0f5cfbb5", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m06", + "name": "Linienmeister", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_m06.glb", + "resource_path": "res://assets/models/unit_m06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m06.blend", + "triangles": 1432, + "mesh_parts": 66, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_ThighArmor", + "Leg2_Greave", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg2_AnkleGold", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_ThighArmor", + "Leg3_Greave", + "Leg3_Toe0", + "Leg3_Toe1", + "Leg3_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_String_1", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1" + ], + "bounds_blender": { + "min": [ + -0.6025153398513794, + -0.6586429476737976, + 0.0 + ], + "max": [ + 0.6025153994560242, + 0.6586429476737976, + 1.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -0.6025153398513794, + 0.0, + -0.6586429476737976 + ], + "max": [ + 0.6025153994560242, + 1.6000001430511475, + 0.6586429476737976 + ] + }, + "scale_applied": 0.9356724937467409, + "blender_version": "5.2.1 LTS", + "sha256": "489574f3e4614bcd75e3486fa8fd6f578195f2f4d6455c86936ad8a8f6d696a6", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m07", + "name": "Klangkolben", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_m07.glb", + "resource_path": "res://assets/models/unit_m07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m07.blend", + "triangles": 740, + "mesh_parts": 27, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_SiegeChassis", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_ResonatorHousing0", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston", + "Body_HousingLatch0__1", + "Body_HousingLatch0_1" + ], + "bounds_blender": { + "min": [ + -0.4213939905166626, + -0.4975554347038269, + 0.0 + ], + "max": [ + 0.4213939905166626, + 0.4975554347038269, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.4213939905166626, + 0.0, + -0.4975554347038269 + ], + "max": [ + 0.4213939905166626, + 1.3499999046325684, + 0.4975554347038269 + ] + }, + "scale_applied": 1.015419270119985, + "blender_version": "5.2.1 LTS", + "sha256": "44b7ea1ec7290f639fa15b985223f03dd92992684ee0257197bafd9663dae643", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m08", + "name": "Resonanzramme", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_m08.glb", + "resource_path": "res://assets/models/unit_m08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m08.blend", + "triangles": 1316, + "mesh_parts": 50, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_ThighArmor", + "Leg2_Greave", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg2_AnkleGold", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_ThighArmor", + "Leg3_Greave", + "Leg3_Toe0", + "Leg3_Toe1", + "Leg3_AnkleGold", + "Body_SiegeChassis", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Body_ResonatorHousing0", + "Weapon_ImpactDisc0", + "Weapon_DiscPiston0", + "Body_HousingLatch0__1", + "Body_HousingLatch0_1", + "Body_ResonatorHousing1", + "Weapon_ImpactDisc1", + "Weapon_DiscPiston1", + "Body_HousingLatch1__1", + "Body_HousingLatch1_1" + ], + "bounds_blender": { + "min": [ + -0.7338443994522095, + -0.5147383809089661, + 0.0 + ], + "max": [ + 0.7338443994522095, + 0.5147383809089661, + 1.4999998807907104 + ] + }, + "bounds_godot": { + "min": [ + -0.7338443994522095, + 0.0, + -0.5147383809089661 + ], + "max": [ + 0.7338443994522095, + 1.4999998807907104, + 0.5147383809089661 + ] + }, + "scale_applied": 1.0952902191196374, + "blender_version": "5.2.1 LTS", + "sha256": "3601cc62c2245e84d58d472b444434fe962851fdc3d663df6572623218063484", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m09", + "name": "Taktspindel", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_m09.glb", + "resource_path": "res://assets/models/unit_m09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m09.blend", + "triangles": 1160, + "mesh_parts": 51, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Breastplate_Rim", + "Body_Breastplate_Face", + "Body_Waist", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "Body_HipPlateL", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_HipPlateR", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye_1", + "Head_Eye1", + "Head_Mouth", + "Body_PendulumStem", + "Body_PendulumBob", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Palm", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "Weapon_Baton", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Palm", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2" + ], + "bounds_blender": { + "min": [ + -0.5013101696968079, + -0.14016570150852203, + 0.0 + ], + "max": [ + 0.5013101696968079, + 0.14016570150852203, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.5013101696968079, + 0.0, + -0.14016570150852203 + ], + "max": [ + 0.5013101696968079, + 1.4500000476837158, + 0.14016570150852203 + ] + }, + "scale_applied": 0.7896659202045064, + "blender_version": "5.2.1 LTS", + "sha256": "11d8104ffbbd31954fd87b23e2901220c9794fd459808491e9ab2e5ac36b3179", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "m10", + "name": "Taktprälat", + "faction": "nietenkonvent", + "palette": "nietenkonvent", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_m10.glb", + "resource_path": "res://assets/models/unit_m10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_m10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/m10.blend", + "triangles": 946, + "mesh_parts": 49, + "parts": [ + "Leg0_Piston", + "Leg0_Shin", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_ThighArmor", + "Leg0_Greave", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg0_AnkleGold", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_ThighArmor", + "Leg1_Greave", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg1_AnkleGold", + "Body_Coat", + "Body_CreamStoleL", + "Body_CoatGoldL", + "Body_CreamStoleR", + "Body_CoatGoldR", + "Body_PendulumOpening", + "Body_PendulumStem", + "Body_PendulumBob", + "Head_Face", + "Head_Eye_1", + "Head_Eye1", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Palm", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "Weapon_Baton", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Palm", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2" + ], + "bounds_blender": { + "min": [ + -0.5444233417510986, + -0.4287889897823334, + 0.0 + ], + "max": [ + 0.5444233417510986, + 0.4287889897823334, + 1.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -0.5444233417510986, + 0.0, + -0.4287889897823334 + ], + "max": [ + 0.5444233417510986, + 1.6000001430511475, + 0.4287889897823334 + ] + }, + "scale_applied": 0.8575779752970936, + "blender_version": "5.2.1 LTS", + "sha256": "43a36780c0ced0869b976bec4fe1423ad7ef14f5b7f68a720da72ad44c28970e", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n01", + "name": "Saummaske", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n01.glb", + "resource_path": "res://assets/models/unit_n01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n01.blend", + "triangles": 1132, + "mesh_parts": 16, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "ArmL", + "WeaponL_Claw", + "ArmR", + "WeaponR_Claw" + ], + "bounds_blender": { + "min": [ + -0.44347620010375977, + -0.19742706418037415, + 0.0 + ], + "max": [ + 0.44347620010375977, + 0.19742707908153534, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.44347620010375977, + 0.0, + -0.19742707908153534 + ], + "max": [ + 0.44347620010375977, + 1.3499999046325684, + 0.19742706418037415 + ] + }, + "scale_applied": 0.855141167579754, + "blender_version": "5.2.1 LTS", + "sha256": "b374d208cc0541a73800b27802507287f349df4b4400f4e56cbeb8461b3579a5", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n02", + "name": "Grenzmaske", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n02.glb", + "resource_path": "res://assets/models/unit_n02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n02.blend", + "triangles": 1156, + "mesh_parts": 18, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay" + ], + "bounds_blender": { + "min": [ + -0.6379754543304443, + -0.21133150160312653, + 0.0 + ], + "max": [ + 0.6379754543304443, + 0.21133150160312653, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.6379754543304443, + 0.0, + -0.21133150160312653 + ], + "max": [ + 0.6379754543304443, + 1.5, + 0.21133150160312653 + ] + }, + "scale_applied": 0.9153671897165055, + "blender_version": "5.2.1 LTS", + "sha256": "fc1a7d3b2d46a9dbbb8834aa1f51189a8389368bfd662f71120d63fcbf2b55a2", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n03", + "name": "Fadentänzer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n03.glb", + "resource_path": "res://assets/models/unit_n03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n03.blend", + "triangles": 934, + "mesh_parts": 13, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "WeaponL_Sickle", + "ArmR", + "WeaponR_Sickle" + ], + "bounds_blender": { + "min": [ + -0.4779128134250641, + -0.16183501482009888, + 0.0 + ], + "max": [ + 0.4779128432273865, + 0.16183499991893768, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.4779128134250641, + 0.0, + -0.16183499991893768 + ], + "max": [ + 0.4779128432273865, + 1.3499999046325684, + 0.16183501482009888 + ] + }, + "scale_applied": 0.772007890355257, + "blender_version": "5.2.1 LTS", + "sha256": "cffec8cc2a300291d8d14431fafc4225e8f7a517709922f1dd8c98d27e7dd086", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n04", + "name": "Saumzertrenner", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n04.glb", + "resource_path": "res://assets/models/unit_n04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n04.blend", + "triangles": 1360, + "mesh_parts": 17, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "ArmR", + "Weapon_ShearPivot", + "Weapon_ShearLower", + "Weapon_ShearLoopLower", + "Weapon_ShearUpper", + "Weapon_ShearLoopUpper", + "Head_CrescentCrown" + ], + "bounds_blender": { + "min": [ + -0.5531443357467651, + -0.19565065205097198, + 0.0 + ], + "max": [ + 0.5531443357467651, + 0.19565066695213318, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5531443357467651, + 0.0, + -0.19565066695213318 + ], + "max": [ + 0.5531443357467651, + 1.5, + 0.19565065205097198 + ] + }, + "scale_applied": 0.8571428571428571, + "blender_version": "5.2.1 LTS", + "sha256": "7796469cefde7029f31a1af60fe298ffe8cd00c1d6653d73a8d748a8814f1bd6", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n05", + "name": "Fernflüsterer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_n05.glb", + "resource_path": "res://assets/models/unit_n05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n05.blend", + "triangles": 1118, + "mesh_parts": 13, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip", + "ArmL", + "ArmR" + ], + "bounds_blender": { + "min": [ + -0.4346340298652649, + -0.2853573262691498, + 0.0 + ], + "max": [ + 0.4346340000629425, + 0.2853573262691498, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.4346340298652649, + 0.0, + -0.2853573262691498 + ], + "max": [ + 0.4346340000629425, + 1.4499999284744263, + 0.2853573262691498 + ] + }, + "scale_applied": 0.8387870445874587, + "blender_version": "5.2.1 LTS", + "sha256": "590fcb19ee024cbf64eb8db4c570ff6afeacf393b8c58788b2192b011797e9b4", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n06", + "name": "Fernrufer", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_n06.glb", + "resource_path": "res://assets/models/unit_n06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n06.blend", + "triangles": 1498, + "mesh_parts": 17, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "ArmL", + "Weapon_HornArchL", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "ArmR", + "Weapon_HornArchR", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ], + "bounds_blender": { + "min": [ + -0.8301005959510803, + -0.3197994828224182, + 0.0 + ], + "max": [ + 0.8301005959510803, + 0.3197995126247406, + 1.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.8301005959510803, + 0.0, + -0.3197995126247406 + ], + "max": [ + 0.8301005959510803, + 1.5999999046325684, + 0.3197994828224182 + ] + }, + "scale_applied": 0.9255581181654716, + "blender_version": "5.2.1 LTS", + "sha256": "590e012f1b09ada25aa5ec48ff78eb60bd1bf3facd6c0b8cebd2a12c13142e58", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n07", + "name": "Glockenschlepper", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_n07.glb", + "resource_path": "res://assets/models/unit_n07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n07.blend", + "triangles": 1274, + "mesh_parts": 15, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Weapon_HangingBell", + "Weapon_BellRim", + "Weapon_ClapperStem", + "Weapon_Clapper", + "ArmL", + "ArmR" + ], + "bounds_blender": { + "min": [ + -0.35533595085144043, + -0.37528085708618164, + 0.0 + ], + "max": [ + 0.35533595085144043, + 0.37528085708618164, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.35533595085144043, + 0.0, + -0.37528085708618164 + ], + "max": [ + 0.35533595085144043, + 1.3499999046325684, + 0.37528085708618164 + ] + }, + "scale_applied": 0.7382346585301032, + "blender_version": "5.2.1 LTS", + "sha256": "8ff3d936bb7329f12177a45e1a7df5324e40e0d49a4d0ecdf49d5da75fd153e7", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n08", + "name": "Hohlgeläut", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_n08.glb", + "resource_path": "res://assets/models/unit_n08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n08.blend", + "triangles": 1482, + "mesh_parts": 18, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Body_CathedralShell", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Weapon_ClapperChain", + "Weapon_Clapper", + "Body_ArchMask", + "Body_ArchMask_Eye_1", + "Body_ArchMask_Eye1", + "Head_SpireL", + "ArmL_Sickle", + "Head_SpireR", + "ArmR_Sickle", + "Head_CentralSpire" + ], + "bounds_blender": { + "min": [ + -0.5439560413360596, + -0.4138086140155792, + 0.0 + ], + "max": [ + 0.5439560413360596, + 0.4138086140155792, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5439560413360596, + 0.0, + -0.4138086140155792 + ], + "max": [ + 0.5439560413360596, + 1.5, + 0.4138086140155792 + ] + }, + "scale_applied": 0.8241758004232191, + "blender_version": "5.2.1 LTS", + "sha256": "d4da0c654034e57a8faecd7d54ab94914cf61881fdad8b0a667cc8d4119d244e", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n09", + "name": "Maskenkantor", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_n09.glb", + "resource_path": "res://assets/models/unit_n09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n09.blend", + "triangles": 1314, + "mesh_parts": 24, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Head_SingingMouth", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_ChoirHorn0__1", + "Head_ChoirHorn0_1" + ], + "bounds_blender": { + "min": [ + -0.543777346611023, + -0.1794917732477188, + 0.0 + ], + "max": [ + 0.543777346611023, + 0.17949174344539642, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.543777346611023, + 0.0, + -0.17949174344539642 + ], + "max": [ + 0.543777346611023, + 1.4500000476837158, + 0.1794917732477188 + ] + }, + "scale_applied": 0.8198173476403533, + "blender_version": "5.2.1 LTS", + "sha256": "af2e461d6b23464a8c3c4d956e0b4ae9a18892f27eaf882973b0a10a8c05fa46", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "n10", + "name": "Vielstimmenkantor", + "faction": "nebelchor", + "palette": "nebelchor", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_n10.glb", + "resource_path": "res://assets/models/unit_n10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_n10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/n10.blend", + "triangles": 1734, + "mesh_parts": 40, + "parts": [ + "Body_WispL", + "Body_TailL", + "Body_WispR", + "Body_TailR", + "Body_CentralFlow", + "Head_Mask", + "Head_Mask_Eye_1", + "Head_Mask_Eye1", + "Head_CurledHood", + "Head_SingingMouth", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_ChoirHorn0__1", + "Head_ChoirHorn0_1", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Mouth", + "Head_ChoirWisp1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn1_1", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp2", + "Head_ChoirHorn2__1", + "Head_ChoirHorn2_1", + "Head_GreatHorn_1", + "Head_GreatHorn1" + ], + "bounds_blender": { + "min": [ + -0.5053644776344299, + -0.17586638033390045, + 0.0 + ], + "max": [ + 0.5053644776344299, + 0.17586638033390045, + 1.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5053644776344299, + 0.0, + -0.17586638033390045 + ], + "max": [ + 0.5053644776344299, + 1.5999999046325684, + 0.17586638033390045 + ] + }, + "scale_applied": 0.7619047965051922, + "blender_version": "5.2.1 LTS", + "sha256": "8c723f7bcb3e363fdf42ee2aed2109e1c9e8a0a532b4b207f5fdf1b557474651", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "w01", + "name": "Dornhopser", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "melee", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w01.blend", + "triangles": 61376, + "offline_sculpt_parts": 18, + "offline_render_triangles": 695666, + "mesh_parts": 166, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_MossHeart", + "Body_WovenBark0", + "Body_WovenBark0_Grain0", + "Body_WovenBark0_Grain1", + "Body_WovenBark1", + "Body_WovenBark1_Grain0", + "Body_WovenBark1_Grain1", + "Body_WovenBark2", + "Body_WovenBark2_Grain0", + "Body_WovenBark2_Grain1", + "Body_WovenBark3", + "Body_WovenBark3_Grain0", + "Body_WovenBark3_Grain1", + "Body_WovenBark4", + "Body_WovenBark4_Grain0", + "Body_WovenBark4_Grain1", + "Body_WovenBark5", + "Body_WovenBark5_Grain0", + "Body_WovenBark5_Grain1", + "Body_ShoulderLeaf0", + "Body_ShoulderLeaf0_Midrib", + "Body_ShoulderLeaf0_Vein0__1", + "Body_ShoulderLeaf0_Vein0_1", + "Body_ShoulderLeaf0_Vein1__1", + "Body_ShoulderLeaf0_Vein1_1", + "Body_ShoulderLeaf0_Vein2__1", + "Body_ShoulderLeaf0_Vein2_1", + "Body_ShoulderLeaf1", + "Body_ShoulderLeaf1_Midrib", + "Body_ShoulderLeaf1_Vein0__1", + "Body_ShoulderLeaf1_Vein0_1", + "Body_ShoulderLeaf1_Vein1__1", + "Body_ShoulderLeaf1_Vein1_1", + "Body_ShoulderLeaf1_Vein2__1", + "Body_ShoulderLeaf1_Vein2_1", + "Body_ShoulderLeaf2", + "Body_ShoulderLeaf2_Midrib", + "Body_ShoulderLeaf2_Vein0__1", + "Body_ShoulderLeaf2_Vein0_1", + "Body_ShoulderLeaf2_Vein1__1", + "Body_ShoulderLeaf2_Vein1_1", + "Body_ShoulderLeaf2_Vein2__1", + "Body_ShoulderLeaf2_Vein2_1", + "Body_ShoulderLeaf3", + "Body_ShoulderLeaf3_Midrib", + "Body_ShoulderLeaf3_Vein0__1", + "Body_ShoulderLeaf3_Vein0_1", + "Body_ShoulderLeaf3_Vein1__1", + "Body_ShoulderLeaf3_Vein1_1", + "Body_ShoulderLeaf3_Vein2__1", + "Body_ShoulderLeaf3_Vein2_1", + "Body_Bark0", + "Body_Bark0_Fissure0", + "Body_Bark0_Fissure1", + "Body_Bark0_Fissure2", + "Body_Bark0_Fissure3", + "Body_Thorn0", + "Body_Bark1", + "Body_Bark1_Fissure0", + "Body_Bark1_Fissure1", + "Body_Bark1_Fissure2", + "Body_Bark1_Fissure3", + "Body_Thorn1", + "Body_Bark2", + "Body_Bark2_Fissure0", + "Body_Bark2_Fissure1", + "Body_Bark2_Fissure2", + "Body_Bark2_Fissure3", + "Body_Thorn2", + "Body_Bark3", + "Body_Bark3_Fissure0", + "Body_Bark3_Fissure1", + "Body_Bark3_Fissure2", + "Body_Bark3_Fissure3", + "Body_Thorn3", + "Body_Bark4", + "Body_Bark4_Fissure0", + "Body_Bark4_Fissure1", + "Body_Bark4_Fissure2", + "Body_Bark4_Fissure3", + "Body_Thorn4", + "Body_Bark5", + "Body_Bark5_Fissure0", + "Body_Bark5_Fissure1", + "Body_Bark5_Fissure2", + "Body_Bark5_Fissure3", + "Body_Thorn5", + "Body_Bark6", + "Body_Bark6_Fissure0", + "Body_Bark6_Fissure1", + "Body_Bark6_Fissure2", + "Body_Bark6_Fissure3", + "Body_Thorn6", + "Body_Bark7", + "Body_Bark7_Fissure0", + "Body_Bark7_Fissure1", + "Body_Bark7_Fissure2", + "Body_Bark7_Fissure3", + "Body_Thorn7", + "Body_Bark8", + "Body_Bark8_Fissure0", + "Body_Bark8_Fissure1", + "Body_Bark8_Fissure2", + "Body_Bark8_Fissure3", + "Body_Thorn8", + "Head_EyeShadow", + "Head_Eye_1", + "Head_Sprout_1", + "Head_Sprout_1_Midrib", + "Head_Sprout_1_Vein0__1", + "Head_Sprout_1_Vein0_1", + "Head_Sprout_1_Vein1__1", + "Head_Sprout_1_Vein1_1", + "Head_Sprout_1_Vein2__1", + "Head_Sprout_1_Vein2_1", + "Head_Eye1", + "Head_Sprout1", + "Head_Sprout1_Midrib", + "Head_Sprout1_Vein0__1", + "Head_Sprout1_Vein0_1", + "Head_Sprout1_Vein1__1", + "Head_Sprout1_Vein1_1", + "Head_Sprout1_Vein2__1", + "Head_Sprout1_Vein2_1", + "Body_Blossom_Petal0", + "Body_Blossom_Petal1", + "Body_Blossom_Petal2", + "Body_Blossom_Petal3", + "Body_Blossom_Petal4", + "Body_Blossom_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5014952421188354, + -0.43660610914230347, + 0.0 + ], + "max": [ + 0.5014951825141907, + 0.43660610914230347, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5014952421188354, + 0.0, + -0.43660610914230347 + ], + "max": [ + 0.5014951825141907, + 1.3499999046325684, + 0.43660610914230347 + ] + }, + "scale_applied": 0.922440014955025, + "blender_version": "5.2.1 LTS", + "sha256": "68ff8429b46cfb249fd02496e8cf64016c73f5f8df9761f21c83beb12c09b1c3", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w02", + "name": "Rankenschnapper", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "melee", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w02.blend", + "triangles": 78020, + "offline_sculpt_parts": 15, + "offline_render_triangles": 810680, + "mesh_parts": 237, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_JawDark", + "Head_Upper_Jaw", + "Head_Upper_Lip0", + "Head_Upper_Lip1", + "Head_Upper_Lip2", + "Head_Upper_Fang0", + "Head_Upper_Fang1", + "Head_Upper_Fang2", + "Head_Upper_Fang3", + "Head_Upper_Fang4", + "Head_Upper_Fang5", + "Head_Upper_Fang6", + "Head_Upper_Fang7", + "Head_Upper_Fang8", + "Head_Lower_Jaw", + "Head_Lower_Lip0", + "Head_Lower_Lip1", + "Head_Lower_Lip2", + "Head_Lower_Fang0", + "Head_Lower_Fang1", + "Head_Lower_Fang2", + "Head_Lower_Fang3", + "Head_Lower_Fang4", + "Head_Lower_Fang5", + "Head_Lower_Fang6", + "Head_Lower_Fang7", + "Head_Lower_Fang8", + "Head_JawLeaf0", + "Head_JawLeaf0_Midrib", + "Head_JawLeaf0_Vein0__1", + "Head_JawLeaf0_Vein0_1", + "Head_JawLeaf0_Vein1__1", + "Head_JawLeaf0_Vein1_1", + "Head_JawLeaf0_Vein2__1", + "Head_JawLeaf0_Vein2_1", + "Head_JawLeaf1", + "Head_JawLeaf1_Midrib", + "Head_JawLeaf1_Vein0__1", + "Head_JawLeaf1_Vein0_1", + "Head_JawLeaf1_Vein1__1", + "Head_JawLeaf1_Vein1_1", + "Head_JawLeaf1_Vein2__1", + "Head_JawLeaf1_Vein2_1", + "Head_JawLeaf2", + "Head_JawLeaf2_Midrib", + "Head_JawLeaf2_Vein0__1", + "Head_JawLeaf2_Vein0_1", + "Head_JawLeaf2_Vein1__1", + "Head_JawLeaf2_Vein1_1", + "Head_JawLeaf2_Vein2__1", + "Head_JawLeaf2_Vein2_1", + "Head_JawLeaf3", + "Head_JawLeaf3_Midrib", + "Head_JawLeaf3_Vein0__1", + "Head_JawLeaf3_Vein0_1", + "Head_JawLeaf3_Vein1__1", + "Head_JawLeaf3_Vein1_1", + "Head_JawLeaf3_Vein2__1", + "Head_JawLeaf3_Vein2_1", + "Head_JawLeaf4", + "Head_JawLeaf4_Midrib", + "Head_JawLeaf4_Vein0__1", + "Head_JawLeaf4_Vein0_1", + "Head_JawLeaf4_Vein1__1", + "Head_JawLeaf4_Vein1_1", + "Head_JawLeaf4_Vein2__1", + "Head_JawLeaf4_Vein2_1", + "Head_JawLeaf5", + "Head_JawLeaf5_Midrib", + "Head_JawLeaf5_Vein0__1", + "Head_JawLeaf5_Vein0_1", + "Head_JawLeaf5_Vein1__1", + "Head_JawLeaf5_Vein1_1", + "Head_JawLeaf5_Vein2__1", + "Head_JawLeaf5_Vein2_1", + "Head_JawFlower_Petal0", + "Head_JawFlower_Petal1", + "Head_JawFlower_Petal2", + "Head_JawFlower_Petal3", + "Head_JawFlower_Petal4", + "Head_JawFlower_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5706138610839844, + -0.6263821721076965, + 0.0 + ], + "max": [ + 0.5706138610839844, + 0.6263822317123413, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.5706138610839844, + 0.0, + -0.6263822317123413 + ], + "max": [ + 0.5706138610839844, + 1.5, + 0.6263821721076965 + ] + }, + "scale_applied": 1.1419287722959226, + "blender_version": "5.2.1 LTS", + "sha256": "e5aecc90518c172f4d05b6f4e337dbf698ca055a62242bf610347cbf64681390", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w03", + "name": "Korkrücken", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "tank", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w03.blend", + "triangles": 84786, + "offline_sculpt_parts": 18, + "offline_render_triangles": 782076, + "mesh_parts": 380, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_InnerMoss", + "Body_Cork0_0", + "Body_Cork0_0_Fissure0", + "Body_Cork0_0_Fissure1", + "Body_Cork0_0_Fissure2", + "Body_Cork0_0_Fissure3", + "Body_Cork0_1", + "Body_Cork0_1_Fissure0", + "Body_Cork0_1_Fissure1", + "Body_Cork0_1_Fissure2", + "Body_Cork0_1_Fissure3", + "Body_Cork0_2", + "Body_Cork0_2_Fissure0", + "Body_Cork0_2_Fissure1", + "Body_Cork0_2_Fissure2", + "Body_Cork0_2_Fissure3", + "Body_Cork0_3", + "Body_Cork0_3_Fissure0", + "Body_Cork0_3_Fissure1", + "Body_Cork0_3_Fissure2", + "Body_Cork0_3_Fissure3", + "Body_Cork0_4", + "Body_Cork0_4_Fissure0", + "Body_Cork0_4_Fissure1", + "Body_Cork0_4_Fissure2", + "Body_Cork0_4_Fissure3", + "Body_Cork0_5", + "Body_Cork0_5_Fissure0", + "Body_Cork0_5_Fissure1", + "Body_Cork0_5_Fissure2", + "Body_Cork0_5_Fissure3", + "Body_Cork0_6", + "Body_Cork0_6_Fissure0", + "Body_Cork0_6_Fissure1", + "Body_Cork0_6_Fissure2", + "Body_Cork0_6_Fissure3", + "Body_Cork1_0", + "Body_Cork1_0_Fissure0", + "Body_Cork1_0_Fissure1", + "Body_Cork1_0_Fissure2", + "Body_Cork1_0_Fissure3", + "Body_Cork1_1", + "Body_Cork1_1_Fissure0", + "Body_Cork1_1_Fissure1", + "Body_Cork1_1_Fissure2", + "Body_Cork1_1_Fissure3", + "Body_Cork1_2", + "Body_Cork1_2_Fissure0", + "Body_Cork1_2_Fissure1", + "Body_Cork1_2_Fissure2", + "Body_Cork1_2_Fissure3", + "Body_Cork1_3", + "Body_Cork1_3_Fissure0", + "Body_Cork1_3_Fissure1", + "Body_Cork1_3_Fissure2", + "Body_Cork1_3_Fissure3", + "Body_Cork1_4", + "Body_Cork1_4_Fissure0", + "Body_Cork1_4_Fissure1", + "Body_Cork1_4_Fissure2", + "Body_Cork1_4_Fissure3", + "Body_Cork1_5", + "Body_Cork1_5_Fissure0", + "Body_Cork1_5_Fissure1", + "Body_Cork1_5_Fissure2", + "Body_Cork1_5_Fissure3", + "Body_Cork1_6", + "Body_Cork1_6_Fissure0", + "Body_Cork1_6_Fissure1", + "Body_Cork1_6_Fissure2", + "Body_Cork1_6_Fissure3", + "Body_Cork2_0", + "Body_Cork2_0_Fissure0", + "Body_Cork2_0_Fissure1", + "Body_Cork2_0_Fissure2", + "Body_Cork2_0_Fissure3", + "Body_Cork2_1", + "Body_Cork2_1_Fissure0", + "Body_Cork2_1_Fissure1", + "Body_Cork2_1_Fissure2", + "Body_Cork2_1_Fissure3", + "Body_Cork2_2", + "Body_Cork2_2_Fissure0", + "Body_Cork2_2_Fissure1", + "Body_Cork2_2_Fissure2", + "Body_Cork2_2_Fissure3", + "Body_Cork2_3", + "Body_Cork2_3_Fissure0", + "Body_Cork2_3_Fissure1", + "Body_Cork2_3_Fissure2", + "Body_Cork2_3_Fissure3", + "Body_Cork2_4", + "Body_Cork2_4_Fissure0", + "Body_Cork2_4_Fissure1", + "Body_Cork2_4_Fissure2", + "Body_Cork2_4_Fissure3", + "Body_Cork2_5", + "Body_Cork2_5_Fissure0", + "Body_Cork2_5_Fissure1", + "Body_Cork2_5_Fissure2", + "Body_Cork2_5_Fissure3", + "Body_Cork2_6", + "Body_Cork2_6_Fissure0", + "Body_Cork2_6_Fissure1", + "Body_Cork2_6_Fissure2", + "Body_Cork2_6_Fissure3", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen" + ], + "bounds_blender": { + "min": [ + -0.48796892166137695, + -0.4879722595214844, + 0.0 + ], + "max": [ + 0.48796892166137695, + 0.4879722595214844, + 1.350000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.48796892166137695, + 0.0, + -0.4879722595214844 + ], + "max": [ + 0.48796892166137695, + 1.350000023841858, + 0.4879722595214844 + ] + }, + "scale_applied": 0.9001111644704809, + "blender_version": "5.2.1 LTS", + "sha256": "bf032894b7094d8dbcc164da190952aef8f467069c23956f39fe59bb905f491b", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w04", + "name": "Ringborke", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "tank", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w04.blend", + "triangles": 134530, + "offline_sculpt_parts": 18, + "offline_render_triangles": 872260, + "mesh_parts": 539, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_InnerMoss", + "Body_OverlappingBark0_0", + "Body_OverlappingBark0_0_Fissure0", + "Body_OverlappingBark0_0_Fissure1", + "Body_OverlappingBark0_0_Fissure2", + "Body_OverlappingBark0_0_Fissure3", + "Body_OverlappingBark0_1", + "Body_OverlappingBark0_1_Fissure0", + "Body_OverlappingBark0_1_Fissure1", + "Body_OverlappingBark0_1_Fissure2", + "Body_OverlappingBark0_1_Fissure3", + "Body_OverlappingBark0_2", + "Body_OverlappingBark0_2_Fissure0", + "Body_OverlappingBark0_2_Fissure1", + "Body_OverlappingBark0_2_Fissure2", + "Body_OverlappingBark0_2_Fissure3", + "Body_OverlappingBark0_3", + "Body_OverlappingBark0_3_Fissure0", + "Body_OverlappingBark0_3_Fissure1", + "Body_OverlappingBark0_3_Fissure2", + "Body_OverlappingBark0_3_Fissure3", + "Body_OverlappingBark0_4", + "Body_OverlappingBark0_4_Fissure0", + "Body_OverlappingBark0_4_Fissure1", + "Body_OverlappingBark0_4_Fissure2", + "Body_OverlappingBark0_4_Fissure3", + "Body_OverlappingBark0_5", + "Body_OverlappingBark0_5_Fissure0", + "Body_OverlappingBark0_5_Fissure1", + "Body_OverlappingBark0_5_Fissure2", + "Body_OverlappingBark0_5_Fissure3", + "Body_OverlappingBark0_6", + "Body_OverlappingBark0_6_Fissure0", + "Body_OverlappingBark0_6_Fissure1", + "Body_OverlappingBark0_6_Fissure2", + "Body_OverlappingBark0_6_Fissure3", + "Body_OverlappingBark0_7", + "Body_OverlappingBark0_7_Fissure0", + "Body_OverlappingBark0_7_Fissure1", + "Body_OverlappingBark0_7_Fissure2", + "Body_OverlappingBark0_7_Fissure3", + "Body_OverlappingBark1_0", + "Body_OverlappingBark1_0_Fissure0", + "Body_OverlappingBark1_0_Fissure1", + "Body_OverlappingBark1_0_Fissure2", + "Body_OverlappingBark1_0_Fissure3", + "Body_OverlappingBark1_1", + "Body_OverlappingBark1_1_Fissure0", + "Body_OverlappingBark1_1_Fissure1", + "Body_OverlappingBark1_1_Fissure2", + "Body_OverlappingBark1_1_Fissure3", + "Body_OverlappingBark1_2", + "Body_OverlappingBark1_2_Fissure0", + "Body_OverlappingBark1_2_Fissure1", + "Body_OverlappingBark1_2_Fissure2", + "Body_OverlappingBark1_2_Fissure3", + "Body_OverlappingBark1_3", + "Body_OverlappingBark1_3_Fissure0", + "Body_OverlappingBark1_3_Fissure1", + "Body_OverlappingBark1_3_Fissure2", + "Body_OverlappingBark1_3_Fissure3", + "Body_OverlappingBark1_4", + "Body_OverlappingBark1_4_Fissure0", + "Body_OverlappingBark1_4_Fissure1", + "Body_OverlappingBark1_4_Fissure2", + "Body_OverlappingBark1_4_Fissure3", + "Body_OverlappingBark1_5", + "Body_OverlappingBark1_5_Fissure0", + "Body_OverlappingBark1_5_Fissure1", + "Body_OverlappingBark1_5_Fissure2", + "Body_OverlappingBark1_5_Fissure3", + "Body_OverlappingBark1_6", + "Body_OverlappingBark1_6_Fissure0", + "Body_OverlappingBark1_6_Fissure1", + "Body_OverlappingBark1_6_Fissure2", + "Body_OverlappingBark1_6_Fissure3", + "Body_OverlappingBark1_7", + "Body_OverlappingBark1_7_Fissure0", + "Body_OverlappingBark1_7_Fissure1", + "Body_OverlappingBark1_7_Fissure2", + "Body_OverlappingBark1_7_Fissure3", + "Body_OverlappingBark2_0", + "Body_OverlappingBark2_0_Fissure0", + "Body_OverlappingBark2_0_Fissure1", + "Body_OverlappingBark2_0_Fissure2", + "Body_OverlappingBark2_0_Fissure3", + "Body_OverlappingBark2_1", + "Body_OverlappingBark2_1_Fissure0", + "Body_OverlappingBark2_1_Fissure1", + "Body_OverlappingBark2_1_Fissure2", + "Body_OverlappingBark2_1_Fissure3", + "Body_OverlappingBark2_2", + "Body_OverlappingBark2_2_Fissure0", + "Body_OverlappingBark2_2_Fissure1", + "Body_OverlappingBark2_2_Fissure2", + "Body_OverlappingBark2_2_Fissure3", + "Body_OverlappingBark2_3", + "Body_OverlappingBark2_3_Fissure0", + "Body_OverlappingBark2_3_Fissure1", + "Body_OverlappingBark2_3_Fissure2", + "Body_OverlappingBark2_3_Fissure3", + "Body_OverlappingBark2_4", + "Body_OverlappingBark2_4_Fissure0", + "Body_OverlappingBark2_4_Fissure1", + "Body_OverlappingBark2_4_Fissure2", + "Body_OverlappingBark2_4_Fissure3", + "Body_OverlappingBark2_5", + "Body_OverlappingBark2_5_Fissure0", + "Body_OverlappingBark2_5_Fissure1", + "Body_OverlappingBark2_5_Fissure2", + "Body_OverlappingBark2_5_Fissure3", + "Body_OverlappingBark2_6", + "Body_OverlappingBark2_6_Fissure0", + "Body_OverlappingBark2_6_Fissure1", + "Body_OverlappingBark2_6_Fissure2", + "Body_OverlappingBark2_6_Fissure3", + "Body_OverlappingBark2_7", + "Body_OverlappingBark2_7_Fissure0", + "Body_OverlappingBark2_7_Fissure1", + "Body_OverlappingBark2_7_Fissure2", + "Body_OverlappingBark2_7_Fissure3", + "Body_Log0_Bark", + "Body_Log0_Cut", + "Body_Log0_Growth0", + "Body_Log0_Growth1", + "Body_Log0_Growth2", + "Body_Log0_Growth3", + "Body_Log0_Growth4", + "Body_Log0_Growth5", + "Body_Log0_RoughEdge0", + "Body_Log0_RoughEdge1", + "Body_Log0_RoughEdge2", + "Body_Log0_RoughEdge3", + "Body_Log0_RoughEdge4", + "Body_Log0_RoughEdge5", + "Body_Log0_RoughEdge6", + "Body_Log0_RoughEdge7", + "Body_Log0_RoughEdge8", + "Body_Log0_RoughEdge9", + "Body_Log0_RoughEdge10", + "Body_Log0_RoughEdge11", + "Body_Log0_RoughEdge12", + "Body_Log0_Split0", + "Body_Log0_Split1", + "Body_Log0_Split2", + "Body_Log1_Bark", + "Body_Log1_Cut", + "Body_Log1_Growth0", + "Body_Log1_Growth1", + "Body_Log1_Growth2", + "Body_Log1_Growth3", + "Body_Log1_Growth4", + "Body_Log1_Growth5", + "Body_Log1_RoughEdge0", + "Body_Log1_RoughEdge1", + "Body_Log1_RoughEdge2", + "Body_Log1_RoughEdge3", + "Body_Log1_RoughEdge4", + "Body_Log1_RoughEdge5", + "Body_Log1_RoughEdge6", + "Body_Log1_RoughEdge7", + "Body_Log1_RoughEdge8", + "Body_Log1_RoughEdge9", + "Body_Log1_RoughEdge10", + "Body_Log1_RoughEdge11", + "Body_Log1_RoughEdge12", + "Body_Log1_Split0", + "Body_Log1_Split1", + "Body_Log1_Split2", + "Body_Log2_Bark", + "Body_Log2_Cut", + "Body_Log2_Growth0", + "Body_Log2_Growth1", + "Body_Log2_Growth2", + "Body_Log2_Growth3", + "Body_Log2_Growth4", + "Body_Log2_Growth5", + "Body_Log2_RoughEdge0", + "Body_Log2_RoughEdge1", + "Body_Log2_RoughEdge2", + "Body_Log2_RoughEdge3", + "Body_Log2_RoughEdge4", + "Body_Log2_RoughEdge5", + "Body_Log2_RoughEdge6", + "Body_Log2_RoughEdge7", + "Body_Log2_RoughEdge8", + "Body_Log2_RoughEdge9", + "Body_Log2_RoughEdge10", + "Body_Log2_RoughEdge11", + "Body_Log2_RoughEdge12", + "Body_Log2_Split0", + "Body_Log2_Split1", + "Body_Log2_Split2", + "Body_Log3_Bark", + "Body_Log3_Cut", + "Body_Log3_Growth0", + "Body_Log3_Growth1", + "Body_Log3_Growth2", + "Body_Log3_Growth3", + "Body_Log3_Growth4", + "Body_Log3_Growth5", + "Body_Log3_RoughEdge0", + "Body_Log3_RoughEdge1", + "Body_Log3_RoughEdge2", + "Body_Log3_RoughEdge3", + "Body_Log3_RoughEdge4", + "Body_Log3_RoughEdge5", + "Body_Log3_RoughEdge6", + "Body_Log3_RoughEdge7", + "Body_Log3_RoughEdge8", + "Body_Log3_RoughEdge9", + "Body_Log3_RoughEdge10", + "Body_Log3_RoughEdge11", + "Body_Log3_RoughEdge12", + "Body_Log3_Split0", + "Body_Log3_Split1", + "Body_Log3_Split2", + "Body_Log4_Bark", + "Body_Log4_Cut", + "Body_Log4_Growth0", + "Body_Log4_Growth1", + "Body_Log4_Growth2", + "Body_Log4_Growth3", + "Body_Log4_Growth4", + "Body_Log4_Growth5", + "Body_Log4_RoughEdge0", + "Body_Log4_RoughEdge1", + "Body_Log4_RoughEdge2", + "Body_Log4_RoughEdge3", + "Body_Log4_RoughEdge4", + "Body_Log4_RoughEdge5", + "Body_Log4_RoughEdge6", + "Body_Log4_RoughEdge7", + "Body_Log4_RoughEdge8", + "Body_Log4_RoughEdge9", + "Body_Log4_RoughEdge10", + "Body_Log4_RoughEdge11", + "Body_Log4_RoughEdge12", + "Body_Log4_Split0", + "Body_Log4_Split1", + "Body_Log4_Split2", + "Body_Log5_Bark", + "Body_Log5_Cut", + "Body_Log5_Growth0", + "Body_Log5_Growth1", + "Body_Log5_Growth2", + "Body_Log5_Growth3", + "Body_Log5_Growth4", + "Body_Log5_Growth5", + "Body_Log5_RoughEdge0", + "Body_Log5_RoughEdge1", + "Body_Log5_RoughEdge2", + "Body_Log5_RoughEdge3", + "Body_Log5_RoughEdge4", + "Body_Log5_RoughEdge5", + "Body_Log5_RoughEdge6", + "Body_Log5_RoughEdge7", + "Body_Log5_RoughEdge8", + "Body_Log5_RoughEdge9", + "Body_Log5_RoughEdge10", + "Body_Log5_RoughEdge11", + "Body_Log5_RoughEdge12", + "Body_Log5_Split0", + "Body_Log5_Split1", + "Body_Log5_Split2", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5741868019104004, + -0.525394082069397, + 0.0 + ], + "max": [ + 0.5741867423057556, + 0.525394082069397, + 1.4999998807907104 + ] + }, + "bounds_godot": { + "min": [ + -0.5741868019104004, + 0.0, + -0.525394082069397 + ], + "max": [ + 0.5741867423057556, + 1.4999998807907104, + 0.525394082069397 + ] + }, + "scale_applied": 0.9691392869232289, + "blender_version": "5.2.1 LTS", + "sha256": "c9411cc996b2aae77620c31dc1281dfdd972216c89a3c7b0acc98edc66f72fa4", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w05", + "name": "Samenschleuder", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "ranged", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_w05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w05.blend", + "triangles": 50536, + "offline_sculpt_parts": 14, + "offline_render_triangles": 493876, + "mesh_parts": 204, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Launcher_Shell", + "Head_Launcher_Rim", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale4_Vein2_1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf1_Vein2_1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen" + ], + "bounds_blender": { + "min": [ + -0.4434923529624939, + -0.44349443912506104, + 0.0 + ], + "max": [ + 0.4434923529624939, + 0.44349443912506104, + 1.4499999284744263 + ] + }, + "bounds_godot": { + "min": [ + -0.4434923529624939, + 0.0, + -0.44349443912506104 + ], + "max": [ + 0.4434923529624939, + 1.4499999284744263, + 0.44349443912506104 + ] + }, + "scale_applied": 0.9698799415431859, + "blender_version": "5.2.1 LTS", + "sha256": "7b5281fa0687e57df36a57639cd3a5325c16b5f7c7e094755cd1b53c14f2b873", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w06", + "name": "Zapfenkrone", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "ranged", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_w06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w06.blend", + "triangles": 62588, + "offline_sculpt_parts": 16, + "offline_render_triangles": 561488, + "mesh_parts": 296, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Launcher_Shell", + "Head_Launcher_Rim", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale5", + "Head_LauncherScale5_Midrib", + "Head_LauncherScale5_Vein0__1", + "Head_LauncherScale5_Vein0_1", + "Head_LauncherScale5_Vein1__1", + "Head_LauncherScale5_Vein1_1", + "Head_LauncherScale5_Vein2__1", + "Head_LauncherScale5_Vein2_1", + "Head_LauncherScale6", + "Head_LauncherScale6_Midrib", + "Head_LauncherScale6_Vein0__1", + "Head_LauncherScale6_Vein0_1", + "Head_LauncherScale6_Vein1__1", + "Head_LauncherScale6_Vein1_1", + "Head_LauncherScale6_Vein2__1", + "Head_LauncherScale6_Vein2_1", + "Head_LauncherScale7", + "Head_LauncherScale7_Midrib", + "Head_LauncherScale7_Vein0__1", + "Head_LauncherScale7_Vein0_1", + "Head_LauncherScale7_Vein1__1", + "Head_LauncherScale7_Vein1_1", + "Head_LauncherScale7_Vein2__1", + "Head_LauncherScale7_Vein2_1", + "Head_LauncherScale8", + "Head_LauncherScale8_Midrib", + "Head_LauncherScale8_Vein0__1", + "Head_LauncherScale8_Vein0_1", + "Head_LauncherScale8_Vein1__1", + "Head_LauncherScale8_Vein1_1", + "Head_LauncherScale8_Vein2__1", + "Head_LauncherScale8_Vein2_1", + "Head_LauncherScale9", + "Head_LauncherScale9_Midrib", + "Head_LauncherScale9_Vein0__1", + "Head_LauncherScale9_Vein0_1", + "Head_LauncherScale9_Vein1__1", + "Head_LauncherScale9_Vein1_1", + "Head_LauncherScale9_Vein2__1", + "Head_LauncherScale9_Vein2_1", + "Head_LauncherScale10", + "Head_LauncherScale10_Midrib", + "Head_LauncherScale10_Vein0__1", + "Head_LauncherScale10_Vein0_1", + "Head_LauncherScale10_Vein1__1", + "Head_LauncherScale10_Vein1_1", + "Head_LauncherScale10_Vein2__1", + "Head_LauncherScale10_Vein2_1", + "Head_LauncherScale11", + "Head_LauncherScale11_Midrib", + "Head_LauncherScale11_Vein0__1", + "Head_LauncherScale11_Vein0_1", + "Head_LauncherScale11_Vein1__1", + "Head_LauncherScale11_Vein1_1", + "Head_LauncherScale11_Vein2__1", + "Head_LauncherScale11_Vein2_1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf1_Vein2_1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen" + ], + "bounds_blender": { + "min": [ + -0.46449750661849976, + -0.46449971199035645, + 0.0 + ], + "max": [ + 0.46449750661849976, + 0.46449971199035645, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.46449750661849976, + 0.0, + -0.46449971199035645 + ], + "max": [ + 0.46449750661849976, + 1.600000023841858, + 0.46449971199035645 + ] + }, + "scale_applied": 1.0158164742306943, + "blender_version": "5.2.1 LTS", + "sha256": "103ec5d6c79dbb19bdc6cd8b00a1ed9811b6c0fc56d57eb8e386d32730754300", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w07", + "name": "Sporenkelch", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "artillery", + "upgraded": false, + "height": 1.35, + "footprint": 1.85, + "file": "unit_w07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w07.blend", + "triangles": 69164, + "offline_sculpt_parts": 9, + "offline_render_triangles": 534224, + "mesh_parts": 366, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Head_Cup0_Shell", + "Head_Cup0_Rim", + "Head_Cup0_Rib0", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Rib1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Rib2", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Rib3", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Rib4", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Rib5", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Rib6", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Rib7", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Rib8", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Rib9", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Rib10", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Rib11", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe11_Vein2_1", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Body_SmallCup0_Shell", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup1_Shell", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Fringe4_Vein2_1" + ], + "bounds_blender": { + "min": [ + -0.5578137040138245, + -0.5487784147262573, + 0.0 + ], + "max": [ + 0.5578137040138245, + 0.5487784147262573, + 1.3499999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.5578137040138245, + 0.0, + -0.5487784147262573 + ], + "max": [ + 0.5578137040138245, + 1.3499999046325684, + 0.5487784147262573 + ] + }, + "scale_applied": 1.0256522914156414, + "blender_version": "5.2.1 LTS", + "sha256": "16e4cb127fee12f5b3757d7bebc742b86b1dbd54c3512934ad21682f8c510ab1", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w08", + "name": "Pilzkathedrale", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "artillery", + "upgraded": true, + "height": 1.5, + "footprint": 1.85, + "file": "unit_w08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w08.blend", + "triangles": 103748, + "offline_sculpt_parts": 11, + "offline_render_triangles": 624368, + "mesh_parts": 700, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Head_Cup0_Shell", + "Head_Cup0_Rim", + "Head_Cup0_Rib0", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Rib1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Rib2", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Rib3", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Rib4", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Rib5", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Rib6", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Rib7", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Rib8", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Rib9", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Rib10", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Rib11", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe11_Vein2_1", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Body_FungalTrunk1", + "Body_FungalTrunk1_Grain0", + "Body_FungalTrunk1_Grain1", + "Body_FungalTrunk1_Grain2", + "Body_FungalTrunk1_Grain3", + "Head_Cup1_Shell", + "Head_Cup1_Rim", + "Head_Cup1_Rib0", + "Head_Cup1_Fringe0", + "Head_Cup1_Fringe0_Midrib", + "Head_Cup1_Fringe0_Vein0__1", + "Head_Cup1_Fringe0_Vein0_1", + "Head_Cup1_Fringe0_Vein1__1", + "Head_Cup1_Fringe0_Vein1_1", + "Head_Cup1_Fringe0_Vein2__1", + "Head_Cup1_Fringe0_Vein2_1", + "Head_Cup1_Rib1", + "Head_Cup1_Fringe1", + "Head_Cup1_Fringe1_Midrib", + "Head_Cup1_Fringe1_Vein0__1", + "Head_Cup1_Fringe1_Vein0_1", + "Head_Cup1_Fringe1_Vein1__1", + "Head_Cup1_Fringe1_Vein1_1", + "Head_Cup1_Fringe1_Vein2__1", + "Head_Cup1_Fringe1_Vein2_1", + "Head_Cup1_Rib2", + "Head_Cup1_Fringe2", + "Head_Cup1_Fringe2_Midrib", + "Head_Cup1_Fringe2_Vein0__1", + "Head_Cup1_Fringe2_Vein0_1", + "Head_Cup1_Fringe2_Vein1__1", + "Head_Cup1_Fringe2_Vein1_1", + "Head_Cup1_Fringe2_Vein2__1", + "Head_Cup1_Fringe2_Vein2_1", + "Head_Cup1_Rib3", + "Head_Cup1_Fringe3", + "Head_Cup1_Fringe3_Midrib", + "Head_Cup1_Fringe3_Vein0__1", + "Head_Cup1_Fringe3_Vein0_1", + "Head_Cup1_Fringe3_Vein1__1", + "Head_Cup1_Fringe3_Vein1_1", + "Head_Cup1_Fringe3_Vein2__1", + "Head_Cup1_Fringe3_Vein2_1", + "Head_Cup1_Rib4", + "Head_Cup1_Fringe4", + "Head_Cup1_Fringe4_Midrib", + "Head_Cup1_Fringe4_Vein0__1", + "Head_Cup1_Fringe4_Vein0_1", + "Head_Cup1_Fringe4_Vein1__1", + "Head_Cup1_Fringe4_Vein1_1", + "Head_Cup1_Fringe4_Vein2__1", + "Head_Cup1_Fringe4_Vein2_1", + "Head_Cup1_Rib5", + "Head_Cup1_Fringe5", + "Head_Cup1_Fringe5_Midrib", + "Head_Cup1_Fringe5_Vein0__1", + "Head_Cup1_Fringe5_Vein0_1", + "Head_Cup1_Fringe5_Vein1__1", + "Head_Cup1_Fringe5_Vein1_1", + "Head_Cup1_Fringe5_Vein2__1", + "Head_Cup1_Fringe5_Vein2_1", + "Head_Cup1_Rib6", + "Head_Cup1_Fringe6", + "Head_Cup1_Fringe6_Midrib", + "Head_Cup1_Fringe6_Vein0__1", + "Head_Cup1_Fringe6_Vein0_1", + "Head_Cup1_Fringe6_Vein1__1", + "Head_Cup1_Fringe6_Vein1_1", + "Head_Cup1_Fringe6_Vein2__1", + "Head_Cup1_Fringe6_Vein2_1", + "Head_Cup1_Rib7", + "Head_Cup1_Fringe7", + "Head_Cup1_Fringe7_Midrib", + "Head_Cup1_Fringe7_Vein0__1", + "Head_Cup1_Fringe7_Vein0_1", + "Head_Cup1_Fringe7_Vein1__1", + "Head_Cup1_Fringe7_Vein1_1", + "Head_Cup1_Fringe7_Vein2__1", + "Head_Cup1_Fringe7_Vein2_1", + "Head_Cup1_Rib8", + "Head_Cup1_Fringe8", + "Head_Cup1_Fringe8_Midrib", + "Head_Cup1_Fringe8_Vein0__1", + "Head_Cup1_Fringe8_Vein0_1", + "Head_Cup1_Fringe8_Vein1__1", + "Head_Cup1_Fringe8_Vein1_1", + "Head_Cup1_Fringe8_Vein2__1", + "Head_Cup1_Fringe8_Vein2_1", + "Head_Cup1_Rib9", + "Head_Cup1_Fringe9", + "Head_Cup1_Fringe9_Midrib", + "Head_Cup1_Fringe9_Vein0__1", + "Head_Cup1_Fringe9_Vein0_1", + "Head_Cup1_Fringe9_Vein1__1", + "Head_Cup1_Fringe9_Vein1_1", + "Head_Cup1_Fringe9_Vein2__1", + "Head_Cup1_Fringe9_Vein2_1", + "Head_Cup1_Rib10", + "Head_Cup1_Fringe10", + "Head_Cup1_Fringe10_Midrib", + "Head_Cup1_Fringe10_Vein0__1", + "Head_Cup1_Fringe10_Vein0_1", + "Head_Cup1_Fringe10_Vein1__1", + "Head_Cup1_Fringe10_Vein1_1", + "Head_Cup1_Fringe10_Vein2__1", + "Head_Cup1_Fringe10_Vein2_1", + "Head_Cup1_Rib11", + "Head_Cup1_Fringe11", + "Head_Cup1_Fringe11_Midrib", + "Head_Cup1_Fringe11_Vein0__1", + "Head_Cup1_Fringe11_Vein0_1", + "Head_Cup1_Fringe11_Vein1__1", + "Head_Cup1_Fringe11_Vein1_1", + "Head_Cup1_Fringe11_Vein2__1", + "Head_Cup1_Fringe11_Vein2_1", + "Weapon_Spore1_0", + "Weapon_Spore1_1", + "Weapon_Spore1_2", + "Weapon_Spore1_3", + "Weapon_Spore1_4", + "Body_FungalTrunk2", + "Body_FungalTrunk2_Grain0", + "Body_FungalTrunk2_Grain1", + "Body_FungalTrunk2_Grain2", + "Body_FungalTrunk2_Grain3", + "Head_Cup2_Shell", + "Head_Cup2_Rim", + "Head_Cup2_Rib0", + "Head_Cup2_Fringe0", + "Head_Cup2_Fringe0_Midrib", + "Head_Cup2_Fringe0_Vein0__1", + "Head_Cup2_Fringe0_Vein0_1", + "Head_Cup2_Fringe0_Vein1__1", + "Head_Cup2_Fringe0_Vein1_1", + "Head_Cup2_Fringe0_Vein2__1", + "Head_Cup2_Fringe0_Vein2_1", + "Head_Cup2_Rib1", + "Head_Cup2_Fringe1", + "Head_Cup2_Fringe1_Midrib", + "Head_Cup2_Fringe1_Vein0__1", + "Head_Cup2_Fringe1_Vein0_1", + "Head_Cup2_Fringe1_Vein1__1", + "Head_Cup2_Fringe1_Vein1_1", + "Head_Cup2_Fringe1_Vein2__1", + "Head_Cup2_Fringe1_Vein2_1", + "Head_Cup2_Rib2", + "Head_Cup2_Fringe2", + "Head_Cup2_Fringe2_Midrib", + "Head_Cup2_Fringe2_Vein0__1", + "Head_Cup2_Fringe2_Vein0_1", + "Head_Cup2_Fringe2_Vein1__1", + "Head_Cup2_Fringe2_Vein1_1", + "Head_Cup2_Fringe2_Vein2__1", + "Head_Cup2_Fringe2_Vein2_1", + "Head_Cup2_Rib3", + "Head_Cup2_Fringe3", + "Head_Cup2_Fringe3_Midrib", + "Head_Cup2_Fringe3_Vein0__1", + "Head_Cup2_Fringe3_Vein0_1", + "Head_Cup2_Fringe3_Vein1__1", + "Head_Cup2_Fringe3_Vein1_1", + "Head_Cup2_Fringe3_Vein2__1", + "Head_Cup2_Fringe3_Vein2_1", + "Head_Cup2_Rib4", + "Head_Cup2_Fringe4", + "Head_Cup2_Fringe4_Midrib", + "Head_Cup2_Fringe4_Vein0__1", + "Head_Cup2_Fringe4_Vein0_1", + "Head_Cup2_Fringe4_Vein1__1", + "Head_Cup2_Fringe4_Vein1_1", + "Head_Cup2_Fringe4_Vein2__1", + "Head_Cup2_Fringe4_Vein2_1", + "Head_Cup2_Rib5", + "Head_Cup2_Fringe5", + "Head_Cup2_Fringe5_Midrib", + "Head_Cup2_Fringe5_Vein0__1", + "Head_Cup2_Fringe5_Vein0_1", + "Head_Cup2_Fringe5_Vein1__1", + "Head_Cup2_Fringe5_Vein1_1", + "Head_Cup2_Fringe5_Vein2__1", + "Head_Cup2_Fringe5_Vein2_1", + "Head_Cup2_Rib6", + "Head_Cup2_Fringe6", + "Head_Cup2_Fringe6_Midrib", + "Head_Cup2_Fringe6_Vein0__1", + "Head_Cup2_Fringe6_Vein0_1", + "Head_Cup2_Fringe6_Vein1__1", + "Head_Cup2_Fringe6_Vein1_1", + "Head_Cup2_Fringe6_Vein2__1", + "Head_Cup2_Fringe6_Vein2_1", + "Head_Cup2_Rib7", + "Head_Cup2_Fringe7", + "Head_Cup2_Fringe7_Midrib", + "Head_Cup2_Fringe7_Vein0__1", + "Head_Cup2_Fringe7_Vein0_1", + "Head_Cup2_Fringe7_Vein1__1", + "Head_Cup2_Fringe7_Vein1_1", + "Head_Cup2_Fringe7_Vein2__1", + "Head_Cup2_Fringe7_Vein2_1", + "Head_Cup2_Rib8", + "Head_Cup2_Fringe8", + "Head_Cup2_Fringe8_Midrib", + "Head_Cup2_Fringe8_Vein0__1", + "Head_Cup2_Fringe8_Vein0_1", + "Head_Cup2_Fringe8_Vein1__1", + "Head_Cup2_Fringe8_Vein1_1", + "Head_Cup2_Fringe8_Vein2__1", + "Head_Cup2_Fringe8_Vein2_1", + "Head_Cup2_Rib9", + "Head_Cup2_Fringe9", + "Head_Cup2_Fringe9_Midrib", + "Head_Cup2_Fringe9_Vein0__1", + "Head_Cup2_Fringe9_Vein0_1", + "Head_Cup2_Fringe9_Vein1__1", + "Head_Cup2_Fringe9_Vein1_1", + "Head_Cup2_Fringe9_Vein2__1", + "Head_Cup2_Fringe9_Vein2_1", + "Head_Cup2_Rib10", + "Head_Cup2_Fringe10", + "Head_Cup2_Fringe10_Midrib", + "Head_Cup2_Fringe10_Vein0__1", + "Head_Cup2_Fringe10_Vein0_1", + "Head_Cup2_Fringe10_Vein1__1", + "Head_Cup2_Fringe10_Vein1_1", + "Head_Cup2_Fringe10_Vein2__1", + "Head_Cup2_Fringe10_Vein2_1", + "Head_Cup2_Rib11", + "Head_Cup2_Fringe11", + "Head_Cup2_Fringe11_Midrib", + "Head_Cup2_Fringe11_Vein0__1", + "Head_Cup2_Fringe11_Vein0_1", + "Head_Cup2_Fringe11_Vein1__1", + "Head_Cup2_Fringe11_Vein1_1", + "Head_Cup2_Fringe11_Vein2__1", + "Head_Cup2_Fringe11_Vein2_1", + "Weapon_Spore2_0", + "Weapon_Spore2_1", + "Weapon_Spore2_2", + "Weapon_Spore2_3", + "Weapon_Spore2_4", + "Body_SmallCup0_Shell", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup1_Shell", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup2_Shell", + "Body_SmallCup2_Rim", + "Body_SmallCup2_Rib0", + "Body_SmallCup2_Fringe0", + "Body_SmallCup2_Fringe0_Midrib", + "Body_SmallCup2_Fringe0_Vein0__1", + "Body_SmallCup2_Fringe0_Vein0_1", + "Body_SmallCup2_Fringe0_Vein1__1", + "Body_SmallCup2_Fringe0_Vein1_1", + "Body_SmallCup2_Fringe0_Vein2__1", + "Body_SmallCup2_Fringe0_Vein2_1", + "Body_SmallCup2_Rib1", + "Body_SmallCup2_Fringe1", + "Body_SmallCup2_Fringe1_Midrib", + "Body_SmallCup2_Fringe1_Vein0__1", + "Body_SmallCup2_Fringe1_Vein0_1", + "Body_SmallCup2_Fringe1_Vein1__1", + "Body_SmallCup2_Fringe1_Vein1_1", + "Body_SmallCup2_Fringe1_Vein2__1", + "Body_SmallCup2_Fringe1_Vein2_1", + "Body_SmallCup2_Rib2", + "Body_SmallCup2_Fringe2", + "Body_SmallCup2_Fringe2_Midrib", + "Body_SmallCup2_Fringe2_Vein0__1", + "Body_SmallCup2_Fringe2_Vein0_1", + "Body_SmallCup2_Fringe2_Vein1__1", + "Body_SmallCup2_Fringe2_Vein1_1", + "Body_SmallCup2_Fringe2_Vein2__1", + "Body_SmallCup2_Fringe2_Vein2_1", + "Body_SmallCup2_Rib3", + "Body_SmallCup2_Fringe3", + "Body_SmallCup2_Fringe3_Midrib", + "Body_SmallCup2_Fringe3_Vein0__1", + "Body_SmallCup2_Fringe3_Vein0_1", + "Body_SmallCup2_Fringe3_Vein1__1", + "Body_SmallCup2_Fringe3_Vein1_1", + "Body_SmallCup2_Fringe3_Vein2__1", + "Body_SmallCup2_Fringe3_Vein2_1", + "Body_SmallCup2_Rib4", + "Body_SmallCup2_Fringe4", + "Body_SmallCup2_Fringe4_Midrib", + "Body_SmallCup2_Fringe4_Vein0__1", + "Body_SmallCup2_Fringe4_Vein0_1", + "Body_SmallCup2_Fringe4_Vein1__1", + "Body_SmallCup2_Fringe4_Vein1_1", + "Body_SmallCup2_Fringe4_Vein2__1", + "Body_SmallCup2_Fringe4_Vein2_1", + "Body_SmallCup3_Shell", + "Body_SmallCup3_Rim", + "Body_SmallCup3_Rib0", + "Body_SmallCup3_Fringe0", + "Body_SmallCup3_Fringe0_Midrib", + "Body_SmallCup3_Fringe0_Vein0__1", + "Body_SmallCup3_Fringe0_Vein0_1", + "Body_SmallCup3_Fringe0_Vein1__1", + "Body_SmallCup3_Fringe0_Vein1_1", + "Body_SmallCup3_Fringe0_Vein2__1", + "Body_SmallCup3_Fringe0_Vein2_1", + "Body_SmallCup3_Rib1", + "Body_SmallCup3_Fringe1", + "Body_SmallCup3_Fringe1_Midrib", + "Body_SmallCup3_Fringe1_Vein0__1", + "Body_SmallCup3_Fringe1_Vein0_1", + "Body_SmallCup3_Fringe1_Vein1__1", + "Body_SmallCup3_Fringe1_Vein1_1", + "Body_SmallCup3_Fringe1_Vein2__1", + "Body_SmallCup3_Fringe1_Vein2_1", + "Body_SmallCup3_Rib2", + "Body_SmallCup3_Fringe2", + "Body_SmallCup3_Fringe2_Midrib", + "Body_SmallCup3_Fringe2_Vein0__1", + "Body_SmallCup3_Fringe2_Vein0_1", + "Body_SmallCup3_Fringe2_Vein1__1", + "Body_SmallCup3_Fringe2_Vein1_1", + "Body_SmallCup3_Fringe2_Vein2__1", + "Body_SmallCup3_Fringe2_Vein2_1", + "Body_SmallCup3_Rib3", + "Body_SmallCup3_Fringe3", + "Body_SmallCup3_Fringe3_Midrib", + "Body_SmallCup3_Fringe3_Vein0__1", + "Body_SmallCup3_Fringe3_Vein0_1", + "Body_SmallCup3_Fringe3_Vein1__1", + "Body_SmallCup3_Fringe3_Vein1_1", + "Body_SmallCup3_Fringe3_Vein2__1", + "Body_SmallCup3_Fringe3_Vein2_1", + "Body_SmallCup3_Rib4", + "Body_SmallCup3_Fringe4", + "Body_SmallCup3_Fringe4_Midrib", + "Body_SmallCup3_Fringe4_Vein0__1", + "Body_SmallCup3_Fringe4_Vein0_1", + "Body_SmallCup3_Fringe4_Vein1__1", + "Body_SmallCup3_Fringe4_Vein1_1", + "Body_SmallCup3_Fringe4_Vein2__1", + "Body_SmallCup3_Fringe4_Vein2_1" + ], + "bounds_blender": { + "min": [ + -0.594677209854126, + -0.5008414387702942, + 0.0 + ], + "max": [ + 0.5946771502494812, + 0.5008414387702942, + 1.5 + ] + }, + "bounds_godot": { + "min": [ + -0.594677209854126, + 0.0, + -0.5008414387702942 + ], + "max": [ + 0.5946771502494812, + 1.5, + 0.5008414387702942 + ] + }, + "scale_applied": 0.9111697095323008, + "blender_version": "5.2.1 LTS", + "sha256": "f20be99b5ae730c6dbd37ca3c635b8953f3d5d852093586ba1790022edea1a75", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w09", + "name": "Tauhüter", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "support", + "upgraded": false, + "height": 1.45, + "footprint": 1.85, + "file": "unit_w09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w09.blend", + "triangles": 52040, + "offline_sculpt_parts": 8, + "offline_render_triangles": 489320, + "mesh_parts": 199, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein2__1", + "Body_TrunkLeaf7_Vein2_1", + "Head_Crown0", + "Head_Crown0_Midrib", + "Head_Crown0_Vein0__1", + "Head_Crown0_Vein0_1", + "Head_Crown0_Vein1__1", + "Head_Crown0_Vein1_1", + "Head_Crown0_Vein2__1", + "Head_Crown0_Vein2_1", + "Head_Crown1", + "Head_Crown1_Midrib", + "Head_Crown1_Vein0__1", + "Head_Crown1_Vein0_1", + "Head_Crown1_Vein1__1", + "Head_Crown1_Vein1_1", + "Head_Crown1_Vein2__1", + "Head_Crown1_Vein2_1", + "Head_Crown2", + "Head_Crown2_Midrib", + "Head_Crown2_Vein0__1", + "Head_Crown2_Vein0_1", + "Head_Crown2_Vein1__1", + "Head_Crown2_Vein1_1", + "Head_Crown2_Vein2__1", + "Head_Crown2_Vein2_1", + "Head_Crown3", + "Head_Crown3_Midrib", + "Head_Crown3_Vein0__1", + "Head_Crown3_Vein0_1", + "Head_Crown3_Vein1__1", + "Head_Crown3_Vein1_1", + "Head_Crown3_Vein2__1", + "Head_Crown3_Vein2_1", + "Head_Crown4", + "Head_Crown4_Midrib", + "Head_Crown4_Vein0__1", + "Head_Crown4_Vein0_1", + "Head_Crown4_Vein1__1", + "Head_Crown4_Vein1_1", + "Head_Crown4_Vein2__1", + "Head_Crown4_Vein2_1", + "Weapon_Basin_Shell", + "Weapon_Basin_Rim", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Water", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_DewOrb", + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen" + ], + "bounds_blender": { + "min": [ + -0.4580939710140228, + -0.4580966830253601, + 0.0 + ], + "max": [ + 0.4580939710140228, + 0.4580966830253601, + 1.4500000476837158 + ] + }, + "bounds_godot": { + "min": [ + -0.4580939710140228, + 0.0, + -0.4580966830253601 + ], + "max": [ + 0.4580939710140228, + 1.4500000476837158, + 0.4580966830253601 + ] + }, + "scale_applied": 0.9039585320704921, + "blender_version": "5.2.1 LTS", + "sha256": "55b1acf214f81151158e1fd7caac2fe9362fcd3fcf67b16c1d7fffebe11b10f1", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "w10", + "name": "Quellgeflecht", + "faction": "wurzelbund", + "palette": "wurzelbund", + "role": "support", + "upgraded": true, + "height": 1.5999999999999999, + "footprint": 1.85, + "file": "unit_w10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_w10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/w10.blend", + "triangles": 61052, + "offline_sculpt_parts": 12, + "offline_render_triangles": 475052, + "mesh_parts": 348, + "parts": [ + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_Moss", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein2__1", + "LegR_Sprout_Vein2_1", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_Moss", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein2__1", + "LegL_Sprout_Vein2_1", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL1_Moss", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Sprout_Vein2_1", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR1_Moss", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Sprout_Vein2_1", + "Body_Arch_1_0", + "Body_Arch_1_0_Grain0", + "Body_Arch_1_0_Grain1", + "Body_Arch_1_0_Grain2", + "Body_Arch_1_1", + "Body_Arch_1_1_Grain0", + "Body_Arch_1_1_Grain1", + "Body_Arch_1_1_Grain2", + "Body_Arch_1_2", + "Body_Arch_1_2_Grain0", + "Body_Arch_1_2_Grain1", + "Body_Arch_1_2_Grain2", + "Body_Arch1_0", + "Body_Arch1_0_Grain0", + "Body_Arch1_0_Grain1", + "Body_Arch1_0_Grain2", + "Body_Arch1_1", + "Body_Arch1_1_Grain0", + "Body_Arch1_1_Grain1", + "Body_Arch1_1_Grain2", + "Body_Arch1_2", + "Body_Arch1_2_Grain0", + "Body_Arch1_2_Grain1", + "Body_Arch1_2_Grain2", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein2__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy11", + "Head_Canopy11_Midrib", + "Head_Canopy11_Vein0__1", + "Head_Canopy11_Vein0_1", + "Head_Canopy11_Vein1__1", + "Head_Canopy11_Vein1_1", + "Head_Canopy11_Vein2__1", + "Head_Canopy11_Vein2_1", + "Head_Canopy12", + "Head_Canopy12_Midrib", + "Head_Canopy12_Vein0__1", + "Head_Canopy12_Vein0_1", + "Head_Canopy12_Vein1__1", + "Head_Canopy12_Vein1_1", + "Head_Canopy12_Vein2__1", + "Head_Canopy12_Vein2_1", + "Head_Canopy13", + "Head_Canopy13_Midrib", + "Head_Canopy13_Vein0__1", + "Head_Canopy13_Vein0_1", + "Head_Canopy13_Vein1__1", + "Head_Canopy13_Vein1_1", + "Head_Canopy13_Vein2__1", + "Head_Canopy13_Vein2_1", + "Head_Canopy14", + "Head_Canopy14_Midrib", + "Head_Canopy14_Vein0__1", + "Head_Canopy14_Vein0_1", + "Head_Canopy14_Vein1__1", + "Head_Canopy14_Vein1_1", + "Head_Canopy14_Vein2__1", + "Head_Canopy14_Vein2_1", + "Head_Canopy15", + "Head_Canopy15_Midrib", + "Head_Canopy15_Vein0__1", + "Head_Canopy15_Vein0_1", + "Head_Canopy15_Vein1__1", + "Head_Canopy15_Vein1_1", + "Head_Canopy15_Vein2__1", + "Head_Canopy15_Vein2_1", + "Head_Canopy16", + "Head_Canopy16_Midrib", + "Head_Canopy16_Vein0__1", + "Head_Canopy16_Vein0_1", + "Head_Canopy16_Vein1__1", + "Head_Canopy16_Vein1_1", + "Head_Canopy16_Vein2__1", + "Head_Canopy16_Vein2_1", + "Head_Canopy17", + "Head_Canopy17_Midrib", + "Head_Canopy17_Vein0__1", + "Head_Canopy17_Vein0_1", + "Head_Canopy17_Vein1__1", + "Head_Canopy17_Vein1_1", + "Head_Canopy17_Vein2__1", + "Head_Canopy17_Vein2_1", + "Head_Canopy18", + "Head_Canopy18_Midrib", + "Head_Canopy18_Vein0__1", + "Head_Canopy18_Vein0_1", + "Head_Canopy18_Vein1__1", + "Head_Canopy18_Vein1_1", + "Head_Canopy18_Vein2__1", + "Head_Canopy18_Vein2_1", + "Head_Canopy19", + "Head_Canopy19_Midrib", + "Head_Canopy19_Vein0__1", + "Head_Canopy19_Vein0_1", + "Head_Canopy19_Vein1__1", + "Head_Canopy19_Vein1_1", + "Head_Canopy19_Vein2__1", + "Head_Canopy19_Vein2_1", + "Head_Canopy20", + "Head_Canopy20_Midrib", + "Head_Canopy20_Vein0__1", + "Head_Canopy20_Vein0_1", + "Head_Canopy20_Vein1__1", + "Head_Canopy20_Vein1_1", + "Head_Canopy20_Vein2__1", + "Head_Canopy20_Vein2_1", + "Head_Canopy21", + "Head_Canopy21_Midrib", + "Head_Canopy21_Vein0__1", + "Head_Canopy21_Vein0_1", + "Head_Canopy21_Vein1__1", + "Head_Canopy21_Vein1_1", + "Head_Canopy21_Vein2__1", + "Head_Canopy21_Vein2_1", + "Head_Canopy22", + "Head_Canopy22_Midrib", + "Head_Canopy22_Vein0__1", + "Head_Canopy22_Vein0_1", + "Head_Canopy22_Vein1__1", + "Head_Canopy22_Vein1_1", + "Head_Canopy22_Vein2__1", + "Head_Canopy22_Vein2_1", + "Head_Canopy23", + "Head_Canopy23_Midrib", + "Head_Canopy23_Vein0__1", + "Head_Canopy23_Vein0_1", + "Head_Canopy23_Vein1__1", + "Head_Canopy23_Vein1_1", + "Head_Canopy23_Vein2__1", + "Head_Canopy23_Vein2_1", + "Weapon_Basin_Shell", + "Weapon_Basin_Rim", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Water", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_Blossom3_Pollen", + "Body_Blossom4_Petal0", + "Body_Blossom4_Petal1", + "Body_Blossom4_Petal2", + "Body_Blossom4_Petal3", + "Body_Blossom4_Petal4", + "Body_Blossom4_Pollen", + "Body_Blossom5_Petal0", + "Body_Blossom5_Petal1", + "Body_Blossom5_Petal2", + "Body_Blossom5_Petal3", + "Body_Blossom5_Petal4", + "Body_Blossom5_Pollen" + ], + "bounds_blender": { + "min": [ + -0.5408053994178772, + -0.5766830444335938, + 0.0 + ], + "max": [ + 0.5408053994178772, + 0.5766830444335938, + 1.600000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.5408053994178772, + 0.0, + -0.5766830444335938 + ], + "max": [ + 0.5408053994178772, + 1.600000023841858, + 0.5766830444335938 + ] + }, + "scale_applied": 1.0671733294701777, + "blender_version": "5.2.1 LTS", + "sha256": "c17b2d1aa6dc2eb4a627a8509362c24c1224e942ac72ab40db3d25e1f78ca340", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported" + }, + { + "id": "s01", + "name": "Nadelspäher", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s01.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s01.blend", + "triangles": 10340, + "mesh_parts": 34, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "Body_LeatherCuirass", + "Head_HoodBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_HoodRim", + "Body_Scarf", + "Body_DiagonalBelt", + "Body_SplitCoat_1", + "Body_TornScarf_1", + "Body_SplitCoat1", + "Body_TornScarf1", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "Weapon_CrossbowStock", + "Weapon_Bow_1", + "Weapon_String_1", + "Weapon_Bow1", + "Weapon_String1", + "Weapon_Bolt" + ], + "bounds_blender": { + "min": [ + -0.4479508697986603, + -0.4116958975791931, + 0.0 + ], + "max": [ + 0.44795089960098267, + 0.4116959273815155, + 1.399999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.4479508697986603, + 0.0, + -0.4116959273815155 + ], + "max": [ + 0.44795089960098267, + 1.399999976158142, + 0.4116958975791931 + ] + }, + "scale_applied": 0.8589844747132427, + "blender_version": "5.2.1 LTS", + "sha256": "af4b60706912d9004b420d37da0d19e0324ffe1d1d182d22214e93a212814df4", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "s02", + "name": "Rostschieber", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s02.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s02.blend", + "triangles": 12040, + "mesh_parts": 38, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Strap", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Strap", + "Body_Armor_Rim", + "Body_Armor_Face", + "Body_Belt", + "Body_Tabard", + "Head_HelmetBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "Weapon_TowerShield_Rim", + "Weapon_TowerShield_Face", + "Weapon_ShieldSpine", + "Weapon_ShieldBoss", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_Corner10_4", + "Weapon_Corner11_16" + ], + "bounds_blender": { + "min": [ + -0.484041690826416, + -0.37111228704452515, + 0.0 + ], + "max": [ + 0.484041690826416, + 0.37111228704452515, + 1.3999998569488525 + ] + }, + "bounds_godot": { + "min": [ + -0.484041690826416, + 0.0, + -0.37111228704452515 + ], + "max": [ + 0.484041690826416, + 1.3999998569488525, + 0.37111228704452515 + ] + }, + "scale_applied": 0.8869464095328802, + "blender_version": "5.2.1 LTS", + "sha256": "64bf431dfd07516aabc01b29529ec6a3e6250a8c122feb254bed75aa0df021a2", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "s03", + "name": "Dunstsänger", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s03.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s03.blend", + "triangles": 7832, + "mesh_parts": 19, + "parts": [ + "Body_LongRobe", + "Head_HoodBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_HoodRim", + "Body_Scarf", + "Body_CreamStole_1", + "Body_RaggedCloak_1", + "Body_CreamStole1", + "Body_RaggedCloak1", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "Weapon_Trumpet" + ], + "bounds_blender": { + "min": [ + -0.592510461807251, + -0.41805312037467957, + 0.0 + ], + "max": [ + 0.592510461807251, + 0.41805312037467957, + 1.399999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.592510461807251, + 0.0, + -0.41805312037467957 + ], + "max": [ + 0.592510461807251, + 1.399999976158142, + 0.41805312037467957 + ] + }, + "scale_applied": 0.8434590980140588, + "blender_version": "5.2.1 LTS", + "sha256": "35c287e7a3885528bc3e69272abacb9cfc5d516b183e323570ad38462234e87c", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "s04", + "name": "Keilbrecher", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.4, + "footprint": 1.85, + "file": "unit_s04.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s04.blend", + "triangles": 10458, + "mesh_parts": 35, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Strap", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Strap", + "Body_Armor_Rim", + "Body_Armor_Face", + "Body_Belt", + "Body_Tabard", + "Head_HelmetBack", + "Head_Visor", + "Head_Eye_1", + "Head_Eye1", + "Head_VisorSlit", + "Head_Crest", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "Weapon_Haft", + "Weapon_Head", + "Weapon_Wedge", + "Weapon_TriangleRim", + "Weapon_TriangleInset" + ], + "bounds_blender": { + "min": [ + -0.638360857963562, + -0.3721802830696106, + 0.0 + ], + "max": [ + 0.638360857963562, + 0.37218034267425537, + 1.3999998569488525 + ] + }, + "bounds_godot": { + "min": [ + -0.638360857963562, + 0.0, + -0.37218034267425537 + ], + "max": [ + 0.638360857963562, + 1.3999998569488525, + 0.3721802830696106 + ] + }, + "scale_applied": 0.8869464095328802, + "blender_version": "5.2.1 LTS", + "sha256": "a160e00f5823e54e93b00b12378357f6e3e20f254ca48890450ebdf3dd1541b7", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "s05", + "name": "Risszehrer", + "faction": "neutral", + "palette": "neutral", + "role": "mercenary", + "upgraded": false, + "height": 1.5499999999999998, + "footprint": 1.85, + "file": "unit_s05.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/unit_s05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_s05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/s05.blend", + "triangles": 10440, + "mesh_parts": 31, + "parts": [ + "LegL_Thigh", + "LegL_Shin", + "LegL_Boot", + "LegR_Thigh", + "LegR_Shin", + "LegR_Boot", + "Body_HollowRib_1", + "Body_RiftEdge_1", + "Body_TornCloth_1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_RiftEdge1", + "Body_TornCloth1", + "Body_HipRag1", + "Head_FacelessHelm", + "Head_MintCrack", + "Head_Antler_1", + "Head_InnerHorn_1", + "Head_Antler1", + "Head_InnerHorn1", + "ArmL_Upper", + "ArmL_Lower", + "ArmL_Glove", + "ArmR_Upper", + "ArmR_Lower", + "ArmR_Glove", + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "Weapon_RiftOrb", + "Weapon_RiftLight" + ], + "bounds_blender": { + "min": [ + -0.4230315685272217, + -0.1786629855632782, + 0.0 + ], + "max": [ + 0.4230315387248993, + 0.178662970662117, + 1.5500001907348633 + ] + }, + "bounds_godot": { + "min": [ + -0.4230315685272217, + 0.0, + -0.178662970662117 + ], + "max": [ + 0.4230315387248993, + 1.5500001907348633, + 0.1786629855632782 + ] + }, + "scale_applied": 0.8728638592455813, + "blender_version": "5.2.1 LTS", + "sha256": "b01c1c71782aff1fcf988aa9032bbdcd4c50e6dc96de62f3bed9f949f4355bef", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "worker", + "name": "Funkenleser", + "faction": "neutral", + "palette": "worker", + "role": "worker", + "upgraded": false, + "height": 1.1, + "footprint": 1.4, + "file": "worker.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/worker.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/worker.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/worker.blend", + "triangles": 24026, + "mesh_parts": 65, + "parts": [ + "LegL_Shin", + "LegL_Boot", + "LegL_Sole", + "LegL_Cuff", + "LegL_ToeRidge0", + "LegL_ToeRidge1", + "LegL_ToeRidge2", + "LegR_Shin", + "LegR_Boot", + "LegR_Sole", + "LegR_Cuff", + "LegR_ToeRidge0", + "LegR_ToeRidge1", + "LegR_ToeRidge2", + "Body_ClayTorso", + "Body_LeatherApron", + "Body_ApronRivet0", + "Body_ApronRivet1", + "Body_ApronRivet2", + "Body_ApronRivet3", + "Body_ApronRivet4", + "Body_ApronRivet5", + "Body_ApronRivet6", + "Body_ToolPocket", + "Body_Harness_1", + "Body_Harness1", + "Head_Hood", + "Head_FaceRecess", + "Head_GoggleSocket_1", + "Head_GoggleLens_1", + "Head_GoggleGlint_1", + "Head_GoggleSocket1", + "Head_GoggleLens1", + "Head_GoggleGlint1", + "Head_Cap", + "Head_LampHousing", + "Head_Lamp", + "Body_Reservoir", + "Body_TankRim0_45", + "Body_TankRim0_79", + "Body_TankBrace0", + "Body_TankBrace1", + "Body_TankBrace2", + "Body_TankBrace3", + "Body_TankBrace4", + "Body_TankBrace5", + "Body_TankBrace6", + "Body_TankBrace7", + "ArmL_Upper", + "ArmL_Forearm", + "ArmL_Elbow", + "ArmL_Glove", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmR_Upper", + "ArmR_Forearm", + "ArmR_Elbow", + "ArmR_Glove", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "WeaponL_Handle", + "WeaponL_Fork", + "WeaponR_Probe" + ], + "bounds_blender": { + "min": [ + -0.4626109004020691, + -0.4145205020904541, + 0.0 + ], + "max": [ + 0.4626109302043915, + 0.4145205020904541, + 1.100000023841858 + ] + }, + "bounds_godot": { + "min": [ + -0.4626109004020691, + 0.0, + -0.4145205020904541 + ], + "max": [ + 0.4626109302043915, + 1.100000023841858, + 0.4145205020904541 + ] + }, + "scale_applied": 1.0471664901050803, + "blender_version": "5.2.1 LTS", + "sha256": "c783cbaf9635bb97576d574f514a1ede4b4d52250b24c0e68f1052281ead017a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 6, + "offline_render_triangles": 103466 + }, + { + "id": "map_lane_segment", + "name": "Lane-Segment", + "faction": "terrain", + "palette": "terrain", + "role": "lane", + "upgraded": false, + "height": 0, + "file": "map_lane_segment.glb", + "triangle_budget": 100000, + "detail_level": "high", + "resource_path": "res://assets/models/map_lane_segment.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/map_lane_segment.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/map_lane_segment.blend", + "triangles": 10700, + "mesh_parts": 45, + "parts": [ + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LRetainingLip", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_RRetainingLip", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeStone_1_0", + "Body_EdgeCap_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeCap_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeCap_1_2", + "Body_EdgeStone_1_3", + "Body_EdgeCap_1_3", + "Body_LightRecess_1_0", + "Body_LightGlass_1_0", + "Body_LightRecess_1_1", + "Body_LightGlass_1_1", + "Body_EdgeStone1_0", + "Body_EdgeCap1_0", + "Body_EdgeStone1_1", + "Body_EdgeCap1_1", + "Body_EdgeStone1_2", + "Body_EdgeCap1_2", + "Body_EdgeStone1_3", + "Body_EdgeCap1_3", + "Body_LightRecess1_0", + "Body_LightGlass1_0", + "Body_LightRecess1_1", + "Body_LightGlass1_1" + ], + "bounds_blender": { + "min": [ + -6.688923358917236, + -2.0, + -0.3499999940395355 + ], + "max": [ + 6.688923358917236, + 2.0, + 0.3935000002384186 + ] + }, + "bounds_godot": { + "min": [ + -6.688923358917236, + -0.3499999940395355, + -2.0 + ], + "max": [ + 6.688923358917236, + 0.3935000002384186, + 2.0 + ] + }, + "scale_applied": 1.0, + "blender_version": "5.2.1 LTS", + "sha256": "32886ae71fc72a188ec72c3931f177d1192043574d31c96da47f6ebfdcb880cc", + "source": "Original parametric bpy geometry; no external meshes or textures.", + "status": "exported" + }, + { + "id": "core_team0", + "name": "Saumkern · Team 0", + "faction": "team0", + "palette": "team0", + "role": "core", + "team": 0, + "upgraded": false, + "height": 2.2, + "footprint": 3.2, + "file": "core_team0.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/core_team0.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team0.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/core_team0.blend", + "triangles": 36652, + "mesh_parts": 64, + "parts": [ + "Body_CoreStep0", + "Body_CoreStepRim0", + "Body_CoreStep1", + "Body_CoreStepRim1", + "Body_CoreStep2", + "Body_CoreStepRim2", + "Body_CoreStep3", + "Body_CoreStepRim3", + "Team_Circle", + "Body_PlinthBlock0", + "Body_Seal0", + "Body_RadialInlay0", + "Body_PlinthBlock1", + "Body_Seal1", + "Body_RadialInlay1", + "Body_PlinthBlock2", + "Body_Seal2", + "Body_RadialInlay2", + "Body_PlinthBlock3", + "Body_Seal3", + "Body_RadialInlay3", + "Body_PlinthBlock4", + "Body_Seal4", + "Body_RadialInlay4", + "Body_PlinthBlock5", + "Body_Seal5", + "Body_RadialInlay5", + "Body_PlinthBlock6", + "Body_Seal6", + "Body_RadialInlay6", + "Body_PlinthBlock7", + "Body_Seal7", + "Body_RadialInlay7", + "Body_PlinthBlock8", + "Body_Seal8", + "Body_RadialInlay8", + "Body_PlinthBlock9", + "Body_Seal9", + "Body_RadialInlay9", + "Body_PlinthBlock10", + "Body_Seal10", + "Body_RadialInlay10", + "Body_PlinthBlock11", + "Body_Seal11", + "Body_RadialInlay11", + "Body_Cradle0", + "Body_CradleCollar0", + "Body_Cradle1", + "Body_CradleCollar1", + "Body_Cradle2", + "Body_CradleCollar2", + "Body_Cradle3", + "Body_CradleCollar3", + "Body_Cradle4", + "Body_CradleCollar4", + "Body_Cradle5", + "Body_CradleCollar5", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Body_CrystalHalo" + ], + "bounds_blender": { + "min": [ + -1.1197097301483154, + -1.1202889680862427, + 0.0 + ], + "max": [ + 1.1197096109390259, + 1.1202890872955322, + 2.200000047683716 + ] + }, + "bounds_godot": { + "min": [ + -1.1197097301483154, + 0.0, + -1.1202890872955322 + ], + "max": [ + 1.1197096109390259, + 2.200000047683716, + 1.1202889680862427 + ] + }, + "scale_applied": 0.9319289899522011, + "blender_version": "5.2.1 LTS", + "sha256": "81a5305fc55482e6ca19524b72787d585211643d8842840efb4bdaf844660181", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 16, + "offline_render_triangles": 344572 + }, + { + "id": "core_team1", + "name": "Saumkern · Team 1", + "faction": "team1", + "palette": "team1", + "role": "core", + "team": 1, + "upgraded": false, + "height": 2.2, + "footprint": 3.2, + "file": "core_team1.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/core_team1.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team1.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/core_team1.blend", + "triangles": 36848, + "mesh_parts": 66, + "parts": [ + "Body_CoreStep0", + "Body_CoreStepRim0", + "Body_CoreStep1", + "Body_CoreStepRim1", + "Body_CoreStep2", + "Body_CoreStepRim2", + "Body_CoreStep3", + "Body_CoreStepRim3", + "Team_Triangle0", + "Team_Triangle1", + "Team_Triangle2", + "Body_PlinthBlock0", + "Body_Seal0", + "Body_RadialInlay0", + "Body_PlinthBlock1", + "Body_Seal1", + "Body_RadialInlay1", + "Body_PlinthBlock2", + "Body_Seal2", + "Body_RadialInlay2", + "Body_PlinthBlock3", + "Body_Seal3", + "Body_RadialInlay3", + "Body_PlinthBlock4", + "Body_Seal4", + "Body_RadialInlay4", + "Body_PlinthBlock5", + "Body_Seal5", + "Body_RadialInlay5", + "Body_PlinthBlock6", + "Body_Seal6", + "Body_RadialInlay6", + "Body_PlinthBlock7", + "Body_Seal7", + "Body_RadialInlay7", + "Body_PlinthBlock8", + "Body_Seal8", + "Body_RadialInlay8", + "Body_PlinthBlock9", + "Body_Seal9", + "Body_RadialInlay9", + "Body_PlinthBlock10", + "Body_Seal10", + "Body_RadialInlay10", + "Body_PlinthBlock11", + "Body_Seal11", + "Body_RadialInlay11", + "Body_Cradle0", + "Body_CradleCollar0", + "Body_Cradle1", + "Body_CradleCollar1", + "Body_Cradle2", + "Body_CradleCollar2", + "Body_Cradle3", + "Body_CradleCollar3", + "Body_Cradle4", + "Body_CradleCollar4", + "Body_Cradle5", + "Body_CradleCollar5", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Body_CrystalHalo" + ], + "bounds_blender": { + "min": [ + -1.1197097301483154, + -1.1202889680862427, + 0.0 + ], + "max": [ + 1.1197096109390259, + 1.1202890872955322, + 2.200000047683716 + ] + }, + "bounds_godot": { + "min": [ + -1.1197097301483154, + 0.0, + -1.1202890872955322 + ], + "max": [ + 1.1197096109390259, + 2.200000047683716, + 1.1202889680862427 + ] + }, + "scale_applied": 0.9319289899522011, + "blender_version": "5.2.1 LTS", + "sha256": "391bd1a1452d56b75c0cfb1e519381fa37c4efa0d9f1a6f99e1e434b9a8747bb", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 16, + "offline_render_triangles": 344768 + }, + { + "id": "e01", + "name": "Splitterling", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.05, + "footprint": 1.85, + "file": "enemy_e01.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e01.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e01.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e01.blend", + "triangles": 19228, + "mesh_parts": 38, + "parts": [ + "Body_Core", + "Body_Carapace0", + "Body_SeamGlow0", + "Body_Carapace1", + "Body_SeamGlow1", + "Body_Carapace2", + "Body_SeamGlow2", + "Body_Carapace3", + "Body_SeamGlow3", + "Head_Skull", + "LegL0_Upper", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Inset", + "LegL1_Upper", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Inset", + "LegL2_Upper", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Inset", + "Head_EyeL", + "Head_MandibleL", + "LegR0_Upper", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Inset", + "LegR1_Upper", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Inset", + "LegR2_Upper", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Inset", + "Head_EyeR", + "Head_MandibleR" + ], + "bounds_blender": { + "min": [ + -0.9224945306777954, + -0.8919363021850586, + 0.0 + ], + "max": [ + 0.9224945306777954, + 0.8919363617897034, + 1.0499999523162842 + ] + }, + "bounds_godot": { + "min": [ + -0.9224945306777954, + 0.0, + -0.8919363617897034 + ], + "max": [ + 0.9224945306777954, + 1.0499999523162842, + 0.8919363021850586 + ] + }, + "scale_applied": 1.1583589145245845, + "blender_version": "5.2.1 LTS", + "sha256": "536a33a8595db0283ea08648a4e5f70b7062850308f08179348afc3abe16134a", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 166318 + }, + { + "id": "e02", + "name": "Schalenläufer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.42, + "footprint": 1.85, + "file": "enemy_e02.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e02.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e02.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e02.blend", + "triangles": 20180, + "mesh_parts": 42, + "parts": [ + "Body_Core", + "Body_Carapace0", + "Body_SeamGlow0", + "Body_Spine0", + "Body_Carapace1", + "Body_SeamGlow1", + "Body_Spine1", + "Body_Carapace2", + "Body_SeamGlow2", + "Body_Spine2", + "Body_Carapace3", + "Body_SeamGlow3", + "Body_Spine3", + "Head_Skull", + "LegL0_Upper", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Inset", + "LegL1_Upper", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Inset", + "LegL2_Upper", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Inset", + "Head_EyeL", + "Head_MandibleL", + "LegR0_Upper", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Inset", + "LegR1_Upper", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Inset", + "LegR2_Upper", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Inset", + "Head_EyeR", + "Head_MandibleR" + ], + "bounds_blender": { + "min": [ + -0.9249999523162842, + -0.8943588137626648, + 0.0 + ], + "max": [ + 0.9249999523162842, + 0.8943588733673096, + 1.4170360565185547 + ] + }, + "bounds_godot": { + "min": [ + -0.9249999523162842, + 0.0, + -0.8943588733673096 + ], + "max": [ + 0.9249999523162842, + 1.4170360565185547, + 0.8943588137626648 + ] + }, + "scale_applied": 1.1615049686592722, + "blender_version": "5.2.1 LTS", + "sha256": "7e48c0663f6cc63ef3d6d9d953d27a75452532ba57336ebd92901714ab0d6da0", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 167270 + }, + { + "id": "e03", + "name": "Nebelrest", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.9, + "footprint": 1.55, + "file": "enemy_e03.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e03.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e03.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e03.blend", + "triangles": 35898, + "mesh_parts": 69, + "parts": [ + "Body_Torso", + "Body_RibL0", + "Body_RibR0", + "Body_RibL1", + "Body_RibR1", + "Body_RibL2", + "Body_RibR2", + "Body_RibL3", + "Body_RibR3", + "Body_RibL4", + "Body_RibR4", + "Head_Skull", + "Head_Face", + "Head_EyeL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "Head_EyeR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_RiftHalo" + ], + "bounds_blender": { + "min": [ + -0.5139663815498352, + -0.3523808419704437, + 0.0 + ], + "max": [ + 0.5139663815498352, + 0.3523808419704437, + 1.899999976158142 + ] + }, + "bounds_godot": { + "min": [ + -0.5139663815498352, + 0.0, + -0.3523808419704437 + ], + "max": [ + 0.5139663815498352, + 1.899999976158142, + 0.3523808419704437 + ] + }, + "scale_applied": 0.9491437054201817, + "blender_version": "5.2.1 LTS", + "sha256": "b5fb8ca2d127392886e3e820cbea85181ad4cb4c85357e61b91bc124e4a9972b", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 9, + "offline_render_triangles": 299628 + }, + { + "id": "e04", + "name": "Fadenschütze", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 1.8, + "footprint": 1.85, + "file": "enemy_e04.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e04.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e04.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e04.blend", + "triangles": 51050, + "mesh_parts": 110, + "parts": [ + "Body_Torso", + "Body_RibL0", + "Body_RibR0", + "Body_RibL1", + "Body_RibR1", + "Body_RibL2", + "Body_RibR2", + "Body_RibL3", + "Body_RibR3", + "Body_RibL4", + "Body_RibR4", + "Head_Skull", + "Head_Face", + "Head_EyeL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "Head_EyeR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_ShinGold", + "LegL_ShinEmber", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_ShinGold", + "LegR_ShinEmber", + "Weapon_Bow_1", + "Weapon_String_1", + "Weapon_Bow1", + "Weapon_String1", + "Weapon_Arrow" + ], + "bounds_blender": { + "min": [ + -0.6411548256874084, + -0.5445201396942139, + 0.0 + ], + "max": [ + 0.6411548256874084, + 0.5445201396942139, + 1.8000000715255737 + ] + }, + "bounds_godot": { + "min": [ + -0.6411548256874084, + 0.0, + -0.5445201396942139 + ], + "max": [ + 0.6411548256874084, + 1.8000000715255737, + 0.5445201396942139 + ] + }, + "scale_applied": 0.9808101893351833, + "blender_version": "5.2.1 LTS", + "sha256": "6f27424be363a48621f09b27956fc79a9697bc3d5339d10dd210ca9bf6f2da90", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 353780 + }, + { + "id": "e05", + "name": "Bruchstampfer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.0, + "footprint": 2.1, + "file": "enemy_e05.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e05.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e05.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e05.blend", + "triangles": 62798, + "mesh_parts": 125, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_BruteCore", + "Body_Chest0__1", + "Body_Chest0_1", + "Body_Chest1__1", + "Body_Chest1_1", + "Body_Chest2__1", + "Body_Chest2_1", + "Body_RiftCrack", + "Body_BackSlab0", + "Body_BackSlab1", + "Body_BackSlab2", + "Body_BackSlab3", + "Head_Mask_Porcelain", + "Head_Mask_EyeSocket_1", + "Head_Mask_EyeLight_1", + "Head_Mask_EyeSocket1", + "Head_Mask_EyeLight1", + "Head_Mask_Nose", + "Head_Mask_MouthSlit0", + "Head_Mask_MouthSlit1", + "Head_Mask_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_StoneHammer", + "ArmL_Knuckle0", + "ArmL_Knuckle1", + "ArmL_Knuckle2", + "ArmL_Cuff", + "Body_ShoulderSpikeL0", + "Body_ShoulderSpikeL1", + "Body_ShoulderSpikeL2", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_StoneHammer", + "ArmR_Knuckle0", + "ArmR_Knuckle1", + "ArmR_Knuckle2", + "ArmR_Cuff", + "Body_ShoulderSpikeR0", + "Body_ShoulderSpikeR1", + "Body_ShoulderSpikeR2" + ], + "bounds_blender": { + "min": [ + -1.0383927822113037, + -0.5819846391677856, + 0.0 + ], + "max": [ + 1.0383927822113037, + 0.5819846391677856, + 2.0 + ] + }, + "bounds_godot": { + "min": [ + -1.0383927822113037, + 0.0, + -0.5819846391677856 + ], + "max": [ + 1.0383927822113037, + 2.0, + 0.5819846391677856 + ] + }, + "scale_applied": 1.1904761431709188, + "blender_version": "5.2.1 LTS", + "sha256": "c50aaa97fdc1b61cf97bed26d40416b0d28f38f159de5f661ff26cb769abf8d8", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 482828 + }, + { + "id": "e06", + "name": "Knotenrufer", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.0, + "footprint": 1.9, + "file": "enemy_e06.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e06.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e06.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e06.blend", + "triangles": 48336, + "mesh_parts": 84, + "parts": [ + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Head_Face_Porcelain", + "Head_Face_EyeSocket_1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeLight1", + "Head_Face_Nose", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffKnot", + "Weapon_StaffHeart", + "Weapon_KnotBranch_1", + "Weapon_KnotBranch1", + "Body_HealingKnot0", + "Body_HealingKnot1", + "Body_HealingKnot2" + ], + "bounds_blender": { + "min": [ + -0.6508334875106812, + -0.38141751289367676, + 0.0 + ], + "max": [ + 0.6508334279060364, + 0.38141751289367676, + 2.000000238418579 + ] + }, + "bounds_godot": { + "min": [ + -0.6508334875106812, + 0.0, + -0.38141751289367676 + ], + "max": [ + 0.6508334279060364, + 2.000000238418579, + 0.38141751289367676 + ] + }, + "scale_applied": 1.0387229339294783, + "blender_version": "5.2.1 LTS", + "sha256": "974519186fc9259d751317a502cff848e2d126bd3cd47df37591296c46186e6f", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 432966 + }, + { + "id": "e07", + "name": "Bruchhirsch", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.6, + "footprint": 2.5, + "file": "enemy_e07.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e07.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e07.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e07.blend", + "triangles": 33800, + "mesh_parts": 49, + "parts": [ + "Body_DeerCore", + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "LegL0_Upper", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Hoof", + "LegL0_ClovenLine", + "LegL1_Upper", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Hoof", + "LegL1_ClovenLine", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_EyeL", + "LegR0_Upper", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Hoof", + "LegR0_ClovenLine", + "LegR1_Upper", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Hoof", + "LegR1_ClovenLine", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Head_AntlerR", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_EyeR", + "Head_Neck", + "Head_Skull", + "Head_Muzzle", + "Head_Nose", + "Body_Tail" + ], + "bounds_blender": { + "min": [ + -0.761934757232666, + -0.9935017824172974, + 0.0 + ], + "max": [ + 0.761934757232666, + 0.9935017824172974, + 2.5999999046325684 + ] + }, + "bounds_godot": { + "min": [ + -0.761934757232666, + 0.0, + -0.9935017824172974 + ], + "max": [ + 0.761934757232666, + 2.5999999046325684, + 0.9935017824172974 + ] + }, + "scale_applied": 0.9961686224146542, + "blender_version": "5.2.1 LTS", + "sha256": "a293fe75a8430a89110b17e61df1b13c4a48fdacd21e3fcde7f070aded387810", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 10, + "offline_render_triangles": 388220 + }, + { + "id": "e08", + "name": "Riegelkoloss", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.6, + "footprint": 2.7, + "file": "enemy_e08.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e08.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e08.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e08.blend", + "triangles": 81240, + "mesh_parts": 222, + "parts": [ + "LegL_InnerThigh", + "LegL_InnerShin", + "LegL_ThighArmor", + "LegL_ShinArmor", + "LegL_HipPivot", + "LegL_HipPin", + "LegL_HipRim", + "LegL_KneePivot", + "LegL_KneePin", + "LegL_KneeRim", + "LegL_AnklePivot", + "LegL_AnklePin", + "LegL_AnkleRim", + "LegL_Toe0", + "LegL_ToeCap0", + "LegL_Toe1", + "LegL_ToeCap1", + "LegL_Toe2", + "LegL_ToeCap2", + "LegL_AnkleCuff", + "LegL_KneeGuard", + "LegR_InnerThigh", + "LegR_InnerShin", + "LegR_ThighArmor", + "LegR_ShinArmor", + "LegR_HipPivot", + "LegR_HipPin", + "LegR_HipRim", + "LegR_KneePivot", + "LegR_KneePin", + "LegR_KneeRim", + "LegR_AnklePivot", + "LegR_AnklePin", + "LegR_AnkleRim", + "LegR_Toe0", + "LegR_ToeCap0", + "LegR_Toe1", + "LegR_ToeCap1", + "LegR_Toe2", + "LegR_ToeCap2", + "LegR_AnkleCuff", + "LegR_KneeGuard", + "Body_ArmoredCore", + "Body_ChestL", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_BorderL", + "Body_SeamL", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowRecess2", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_Merlon0", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap3", + "Body_LFastener0_59_Seat", + "Body_LFastener0_59_Head", + "Body_LFastener1_19_Seat", + "Body_LFastener1_19_Head", + "Body_ChestR", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_BorderR", + "Body_SeamR", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowRecess2", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_Merlon0", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap3", + "Body_RFastener0_59_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener1_19_Seat", + "Body_RFastener1_19_Head", + "Head_FurnaceRecess", + "Head_Fire", + "Head_FireHeart", + "Body_CenterGold_1", + "Body_CenterGold1", + "Body_BottomGold", + "Head_Crown_StoneKeep", + "Head_Crown_LowerCornice", + "Head_Crown_UpperCornice", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowFire0", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowFire1", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowRecess2", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel2", + "Head_Crown_Merlon0", + "Head_Crown_MerlonCap0", + "Head_Crown_Merlon1", + "Head_Crown_MerlonCap1", + "Head_Crown_Merlon2", + "Head_Crown_MerlonCap2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap3", + "Body_SpineGold", + "Body_RiftHorn_1", + "Body_RiftHorn1" + ], + "bounds_blender": { + "min": [ + -1.1929707527160645, + -0.5861989855766296, + 0.0 + ], + "max": [ + 1.1929707527160645, + 0.5861990451812744, + 2.6000001430511475 + ] + }, + "bounds_godot": { + "min": [ + -1.1929707527160645, + 0.0, + -0.5861990451812744 + ], + "max": [ + 1.1929707527160645, + 2.6000001430511475, + 0.5861989855766296 + ] + }, + "scale_applied": 1.4130434526274926, + "blender_version": "5.2.1 LTS", + "sha256": "c196108262b2708200b4fee2a4a69c5c8f7551fabb90d296ce7bf482f44e4049", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 470520 + }, + { + "id": "e09", + "name": "Maskenrichter", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.9, + "footprint": 2.6, + "file": "enemy_e09.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e09.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e09.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e09.blend", + "triangles": 57310, + "mesh_parts": 135, + "parts": [ + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Head_Face_Porcelain", + "Head_Face_EyeSocket_1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeLight1", + "Head_Face_Nose", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "ArmL_UpperCore", + "ArmL_ForearmCore", + "ArmL_Elbow", + "ArmL_UpperArmor", + "ArmL_ForearmArmor", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperBandRivet_Head", + "ArmL_WristBand", + "ArmL_WristBandRivet_Seat", + "ArmL_WristBandRivet_Head", + "ArmL_Palm", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_Thumb", + "ArmL_Pauldron", + "ArmR_UpperCore", + "ArmR_ForearmCore", + "ArmR_Elbow", + "ArmR_UpperArmor", + "ArmR_ForearmArmor", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperBandRivet_Head", + "ArmR_WristBand", + "ArmR_WristBandRivet_Seat", + "ArmR_WristBandRivet_Head", + "ArmR_Palm", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_Thumb", + "ArmR_Pauldron", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffKnot", + "Weapon_StaffHeart", + "Weapon_KnotBranch_1", + "Weapon_KnotBranch1", + "Body_JudgeHalo", + "Body_JudgeGlow", + "Body_CourtMask0_Porcelain", + "Body_CourtMask0_EyeSocket_1", + "Body_CourtMask0_EyeLight_1", + "Body_CourtMask0_EyeSocket1", + "Body_CourtMask0_EyeLight1", + "Body_CourtMask0_Nose", + "Body_CourtMask0_MouthSlit0", + "Body_CourtMask0_MouthSlit1", + "Body_CourtMask0_MouthSlit2", + "Body_CrownSpike0", + "Body_CourtMask1_Porcelain", + "Body_CourtMask1_EyeSocket_1", + "Body_CourtMask1_EyeLight_1", + "Body_CourtMask1_EyeSocket1", + "Body_CourtMask1_EyeLight1", + "Body_CourtMask1_Nose", + "Body_CourtMask1_MouthSlit0", + "Body_CourtMask1_MouthSlit1", + "Body_CourtMask1_MouthSlit2", + "Body_CrownSpike1", + "Body_CourtMask2_Porcelain", + "Body_CourtMask2_EyeSocket_1", + "Body_CourtMask2_EyeLight_1", + "Body_CourtMask2_EyeSocket1", + "Body_CourtMask2_EyeLight1", + "Body_CourtMask2_Nose", + "Body_CourtMask2_MouthSlit0", + "Body_CourtMask2_MouthSlit1", + "Body_CourtMask2_MouthSlit2", + "Body_CrownSpike2", + "Body_CourtMask3_Porcelain", + "Body_CourtMask3_EyeSocket_1", + "Body_CourtMask3_EyeLight_1", + "Body_CourtMask3_EyeSocket1", + "Body_CourtMask3_EyeLight1", + "Body_CourtMask3_Nose", + "Body_CourtMask3_MouthSlit0", + "Body_CourtMask3_MouthSlit1", + "Body_CourtMask3_MouthSlit2", + "Body_CrownSpike3", + "Body_CourtMask4_Porcelain", + "Body_CourtMask4_EyeSocket_1", + "Body_CourtMask4_EyeLight_1", + "Body_CourtMask4_EyeSocket1", + "Body_CourtMask4_EyeLight1", + "Body_CourtMask4_Nose", + "Body_CourtMask4_MouthSlit0", + "Body_CourtMask4_MouthSlit1", + "Body_CourtMask4_MouthSlit2", + "Body_CrownSpike4", + "Body_Chains_1", + "Body_Chains1" + ], + "bounds_blender": { + "min": [ + -0.8772106170654297, + -0.4426944851875305, + 0.0 + ], + "max": [ + 0.8772106170654297, + 0.4426945149898529, + 2.9000000953674316 + ] + }, + "bounds_godot": { + "min": [ + -0.8772106170654297, + 0.0, + -0.4426945149898529 + ], + "max": [ + 0.8772106170654297, + 2.9000000953674316, + 0.4426944851875305 + ] + }, + "scale_applied": 1.2055999949252425, + "blender_version": "5.2.1 LTS", + "sha256": "52fc2b44a0c0b9b4f343412d4c4858db9ec23adf0d6383fdfc59b8c98bb05aa9", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 12, + "offline_render_triangles": 441940 + }, + { + "id": "e10", + "name": "Schlundkrone", + "faction": "rift", + "palette": "neutral", + "role": "enemy", + "upgraded": false, + "height": 2.9, + "footprint": 3.1, + "file": "enemy_e10.glb", + "triangle_budget": 180000, + "detail_level": "high", + "resource_path": "res://assets/models/enemy_e10.glb", + "export_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e10.glb", + "blend_path": "/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase4/blend/e10.blend", + "triangles": 64694, + "mesh_parts": 82, + "parts": [ + "Body_CrownCore", + "LegL0_Inner", + "LegL0_Thigh", + "LegL0_Shin", + "LegL0_Joint", + "LegL0_Claw0", + "LegL0_Claw1", + "LegL0_Claw2", + "LegL1_Inner", + "LegL1_Thigh", + "LegL1_Shin", + "LegL1_Joint", + "LegL1_Claw0", + "LegL1_Claw1", + "LegL1_Claw2", + "Body_ShellL0", + "Body_RidgeL0", + "Body_ShellL1", + "Body_RidgeL1", + "Body_ShellL2", + "Body_RidgeL2", + "Body_ShellL3", + "Body_RidgeL3", + "LegR0_Inner", + "LegR0_Thigh", + "LegR0_Shin", + "LegR0_Joint", + "LegR0_Claw0", + "LegR0_Claw1", + "LegR0_Claw2", + "LegR1_Inner", + "LegR1_Thigh", + "LegR1_Shin", + "LegR1_Joint", + "LegR1_Claw0", + "LegR1_Claw1", + "LegR1_Claw2", + "Body_ShellR0", + "Body_RidgeR0", + "Body_ShellR1", + "Body_RidgeR1", + "Body_ShellR2", + "Body_RidgeR2", + "Body_ShellR3", + "Body_RidgeR3", + "Head_MawVoid", + "Head_MawRim", + "Head_RiftThroat", + "Head_Tooth0", + "Head_Tooth1", + "Head_Tooth2", + "Head_Tooth3", + "Head_Tooth4", + "Head_Tooth5", + "Head_Tooth6", + "Head_Tooth7", + "Head_Tooth8", + "Head_Tooth9", + "Head_Tooth10", + "Head_Tooth11", + "Head_Tooth12", + "Head_Tooth13", + "Head_Brow_1", + "Head_Eye_1", + "Head_Brow1", + "Head_Eye1", + "Head_CrownBand", + "Head_CrownPoint0", + "Head_CrownGem0", + "Head_CrownPoint1", + "Head_CrownGem1", + "Head_CrownPoint2", + "Head_CrownGem2", + "Head_CrownPoint3", + "Head_CrownGem3", + "Head_CrownPoint4", + "Head_CrownGem4", + "Head_CrownPoint5", + "Head_CrownGem5", + "Head_CrownPoint6", + "Head_CrownGem6", + "Body_Tail" + ], + "bounds_blender": { + "min": [ + -1.152681827545166, + -1.2775990962982178, + 0.0 + ], + "max": [ + 1.152681827545166, + 1.2775990962982178, + 2.8999996185302734 + ] + }, + "bounds_godot": { + "min": [ + -1.152681827545166, + 0.0, + -1.2775990962982178 + ], + "max": [ + 1.152681827545166, + 2.8999996185302734, + 1.2775990962982178 + ] + }, + "scale_applied": 1.3497444874946902, + "blender_version": "5.2.1 LTS", + "sha256": "92fd4fed1e6324a5ba6adf143ae6c1e14ea022d6e63bb3bcae124326a15850d5", + "source": "Original authored bpy geometry. Sculpted surface relief and editable high-resolution modifiers; runtime materials are assigned by Godot.", + "status": "exported", + "offline_sculpt_parts": 18, + "offline_render_triangles": 708914 + } + ] +} diff --git a/assets/ui/controls/choice_off.svg b/assets/ui/controls/choice_off.svg new file mode 100644 index 0000000..2f57690 --- /dev/null +++ b/assets/ui/controls/choice_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/ui/controls/choice_off.svg.import b/assets/ui/controls/choice_off.svg.import new file mode 100644 index 0000000..9289d07 --- /dev/null +++ b/assets/ui/controls/choice_off.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://btvw8edv0m40u" +path="res://.godot/imported/choice_off.svg-105930699719af2aed0b2ffaf78a018a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/controls/choice_off.svg" +dest_files=["res://.godot/imported/choice_off.svg-105930699719af2aed0b2ffaf78a018a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/controls/choice_on.svg b/assets/ui/controls/choice_on.svg new file mode 100644 index 0000000..4c85eda --- /dev/null +++ b/assets/ui/controls/choice_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/ui/controls/choice_on.svg.import b/assets/ui/controls/choice_on.svg.import new file mode 100644 index 0000000..4cee58c --- /dev/null +++ b/assets/ui/controls/choice_on.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ck4v7xwat0q07" +path="res://.godot/imported/choice_on.svg-91f6532c222c73150e831e47c07fcfc8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/controls/choice_on.svg" +dest_files=["res://.godot/imported/choice_on.svg-91f6532c222c73150e831e47c07fcfc8.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/controls/toggle_off.svg b/assets/ui/controls/toggle_off.svg new file mode 100644 index 0000000..f069a1b --- /dev/null +++ b/assets/ui/controls/toggle_off.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/ui/controls/toggle_off.svg.import b/assets/ui/controls/toggle_off.svg.import new file mode 100644 index 0000000..302e37f --- /dev/null +++ b/assets/ui/controls/toggle_off.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://5qqc207k164n" +path="res://.godot/imported/toggle_off.svg-8792b85756b225bd3fe6c1d654f653d4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/controls/toggle_off.svg" +dest_files=["res://.godot/imported/toggle_off.svg-8792b85756b225bd3fe6c1d654f653d4.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/controls/toggle_on.svg b/assets/ui/controls/toggle_on.svg new file mode 100644 index 0000000..b024572 --- /dev/null +++ b/assets/ui/controls/toggle_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/ui/controls/toggle_on.svg.import b/assets/ui/controls/toggle_on.svg.import new file mode 100644 index 0000000..e18ebc3 --- /dev/null +++ b/assets/ui/controls/toggle_on.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://fvxfana3qx3s" +path="res://.godot/imported/toggle_on.svg-7e8b7a0af2fb7064cfdb22a585072698.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/controls/toggle_on.svg" +dest_files=["res://.godot/imported/toggle_on.svg-7e8b7a0af2fb7064cfdb22a585072698.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/emblems/glutpakt.svg b/assets/ui/emblems/glutpakt.svg new file mode 100644 index 0000000..7ee3dc5 --- /dev/null +++ b/assets/ui/emblems/glutpakt.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/ui/emblems/glutpakt.svg.import b/assets/ui/emblems/glutpakt.svg.import new file mode 100644 index 0000000..066474d --- /dev/null +++ b/assets/ui/emblems/glutpakt.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://devr4kvp73edj" +path="res://.godot/imported/glutpakt.svg-fb27327d0223b38bedbf9d3ba6ba6b87.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/emblems/glutpakt.svg" +dest_files=["res://.godot/imported/glutpakt.svg-fb27327d0223b38bedbf9d3ba6ba6b87.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/emblems/saumwacht.svg b/assets/ui/emblems/saumwacht.svg new file mode 100644 index 0000000..ba92591 --- /dev/null +++ b/assets/ui/emblems/saumwacht.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/ui/emblems/saumwacht.svg.import b/assets/ui/emblems/saumwacht.svg.import new file mode 100644 index 0000000..d468ae3 --- /dev/null +++ b/assets/ui/emblems/saumwacht.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bq2fvwjdtb6ds" +path="res://.godot/imported/saumwacht.svg-3d6935f9b391bfcc23763b903f998d14.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/emblems/saumwacht.svg" +dest_files=["res://.godot/imported/saumwacht.svg-3d6935f9b391bfcc23763b903f998d14.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/emblems/wurzelbund.svg b/assets/ui/emblems/wurzelbund.svg new file mode 100644 index 0000000..9d57562 --- /dev/null +++ b/assets/ui/emblems/wurzelbund.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/ui/emblems/wurzelbund.svg.import b/assets/ui/emblems/wurzelbund.svg.import new file mode 100644 index 0000000..01f1a60 --- /dev/null +++ b/assets/ui/emblems/wurzelbund.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c12i1jdr4o7bm" +path="res://.godot/imported/wurzelbund.svg-542611734bc5b4a34c55e69641679314.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/emblems/wurzelbund.svg" +dest_files=["res://.godot/imported/wurzelbund.svg-542611734bc5b4a34c55e69641679314.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/assets/ui/ui_button_disabled.png b/assets/ui/ui_button_disabled.png new file mode 100644 index 0000000..538b520 Binary files /dev/null and b/assets/ui/ui_button_disabled.png differ diff --git a/assets/ui/ui_button_disabled.png.import b/assets/ui/ui_button_disabled.png.import new file mode 100644 index 0000000..84248ae --- /dev/null +++ b/assets/ui/ui_button_disabled.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cymjmjdpbbn2q" +path="res://.godot/imported/ui_button_disabled.png-dfbd265cd0dc17528c0b32c69cfe4bcc.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_button_disabled.png" +dest_files=["res://.godot/imported/ui_button_disabled.png-dfbd265cd0dc17528c0b32c69cfe4bcc.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/ui/ui_button_hover.png b/assets/ui/ui_button_hover.png new file mode 100644 index 0000000..43f512b Binary files /dev/null and b/assets/ui/ui_button_hover.png differ diff --git a/assets/ui/ui_button_hover.png.import b/assets/ui/ui_button_hover.png.import new file mode 100644 index 0000000..248a328 --- /dev/null +++ b/assets/ui/ui_button_hover.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://do1jpf3ahfam2" +path="res://.godot/imported/ui_button_hover.png-736e082ad74a862a71e4f1912af3d867.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_button_hover.png" +dest_files=["res://.godot/imported/ui_button_hover.png-736e082ad74a862a71e4f1912af3d867.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/ui/ui_button_normal.png b/assets/ui/ui_button_normal.png new file mode 100644 index 0000000..62d34d4 Binary files /dev/null and b/assets/ui/ui_button_normal.png differ diff --git a/assets/ui/ui_button_normal.png.import b/assets/ui/ui_button_normal.png.import new file mode 100644 index 0000000..f0601dc --- /dev/null +++ b/assets/ui/ui_button_normal.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dv5arsy302gr3" +path="res://.godot/imported/ui_button_normal.png-46e39ccfc88867a1f41061304a2627a6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_button_normal.png" +dest_files=["res://.godot/imported/ui_button_normal.png-46e39ccfc88867a1f41061304a2627a6.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/ui/ui_button_pressed.png b/assets/ui/ui_button_pressed.png new file mode 100644 index 0000000..05622c3 Binary files /dev/null and b/assets/ui/ui_button_pressed.png differ diff --git a/assets/ui/ui_button_pressed.png.import b/assets/ui/ui_button_pressed.png.import new file mode 100644 index 0000000..52954fe --- /dev/null +++ b/assets/ui/ui_button_pressed.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://3ngi0ne4oydy" +path="res://.godot/imported/ui_button_pressed.png-49c9a7ccc14810c99245514bedde66a5.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_button_pressed.png" +dest_files=["res://.godot/imported/ui_button_pressed.png-49c9a7ccc14810c99245514bedde66a5.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/ui/ui_panel_a.png b/assets/ui/ui_panel_a.png new file mode 100644 index 0000000..f807540 Binary files /dev/null and b/assets/ui/ui_panel_a.png differ diff --git a/assets/ui/ui_panel_a.png.import b/assets/ui/ui_panel_a.png.import new file mode 100644 index 0000000..11c5417 --- /dev/null +++ b/assets/ui/ui_panel_a.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://br3267rt34trv" +path="res://.godot/imported/ui_panel_a.png-6abb3a318cfc1ec64aa7f6f7cb65511d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_panel_a.png" +dest_files=["res://.godot/imported/ui_panel_a.png-6abb3a318cfc1ec64aa7f6f7cb65511d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/assets/ui/ui_panel_b.png b/assets/ui/ui_panel_b.png new file mode 100644 index 0000000..cc1fd41 Binary files /dev/null and b/assets/ui/ui_panel_b.png differ diff --git a/assets/ui/ui_panel_b.png.import b/assets/ui/ui_panel_b.png.import new file mode 100644 index 0000000..2706956 --- /dev/null +++ b/assets/ui/ui_panel_b.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dg71by3m067r4" +path="res://.godot/imported/ui_panel_b.png-17ff592448758f099a4151c821bfad63.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/ui/ui_panel_b.png" +dest_files=["res://.godot/imported/ui_panel_b.png-17ff592448758f099a4151c821bfad63.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/docs/QA.md b/docs/QA.md new file mode 100644 index 0000000..1713c47 --- /dev/null +++ b/docs/QA.md @@ -0,0 +1,24 @@ +# Saumwacht · Demo-QA + +Aktuell: **[phase20-QA.md](phase20-QA.md)** · Hauptmenü, Bundauswahl, visuelle Identität · Demo 0.15.0. + +| Bericht | Inhalt | +| --- | --- | +| [phase20-QA.md](phase20-QA.md) | Hauptmenü, Bundwahl, Theme, Eingabeschutz, Bühne, Laufzeit, Demo 0.15.0 | +| [phase19-QA.md](phase19-QA.md) | Glasballiste g06, Ballisten-Läufer, Fußkontakt, Schuss- und Nachladeablauf, Spielkamera | +| [phase18-QA.md](phase18-QA.md) | Funkenlanze g05, Fernkampf-Skelett, Lanzengewehr-Clips | +| [phase17-QA.md](phase17-QA.md) | Fähigkeitsauslöser, Werkzeugkontakte, Blattmaterialien, tatsächliche Paketmodelle | +| [phase13-QA.md](phase13-QA.md) | Beleuchtung, Menü, HUD | +| [phase12-QA.md](phase12-QA.md) | Funkenleser, Arbeitszyklus, Kernreaktion | +| [phase11-QA.md](phase11-QA.md) | Ringborke, Paketläufe 0.11 | +| [phase10-QA.md](phase10-QA.md) | Landschaft und Interface | + +```bash +godot --path . --resolution 1920x1080 res://tools/verify_menu.tscn +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +godot --path . res://tools/ui_review.tscn +godot --path . res://tools/funken_review.tscn +godot --path . res://tools/glass_review.tscn +``` diff --git a/docs/ability-animation-verification.json b/docs/ability-animation-verification.json new file mode 100644 index 0000000..f0dc376 --- /dev/null +++ b/docs/ability-animation-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 33, + "failures": [] +} \ No newline at end of file diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..00888eb --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,198 @@ +# Saumwacht · Architektur der Glutpakt-Slice + +Stand: 16. September 2026. Das Projekt implementiert ein lokales Match mit Godot 4 und GDScript: zehn Glutpakt-Wächter, wahlweise 20 Wellen mit vier Bossen oder acht Wellen mit zwei Bossen, fünf Söldner und eine Gegner-KI in zwei Stufen. `AssetLibrary` bindet die Icons und GLB-Modelle aus Phase 3/4 ein; zehn hochdetaillierte Gegnermodelle ergänzen sie. Weitere Fraktionen sind im Dossier und als Assets vorbereitet. + +GDScript eignet sich hier für kurze Iterationen, direkte Godot-Integration und einen Start ohne zusätzliche .NET-Laufzeit. Die Logik verwendet Typangaben an Schnittstellen und für zentrale Werte. Ein späterer Wechsel einzelner rechenintensiver Teile ist möglich, sollte aber erst nach Profiling erfolgen. Die ausführbare Referenz ist die lokale Godot-Version 4.7.2. + +## Projekt und Szenen + +```text +saumwacht-godot/ +├── project.godot +├── scenes/main.tscn +├── scripts/ +│ ├── main.gd +│ ├── autoload/ +│ │ ├── game_state.gd +│ │ ├── wave_manager.gd +│ │ └── economy_manager.gd +│ ├── data/data_catalog.gd +│ ├── ai/simple_ai.gd +│ ├── combat/ +│ │ ├── battle_controller.gd +│ │ ├── unit.gd +│ │ ├── movement_component.gd +│ │ ├── targeting_component.gd +│ │ ├── attack_component.gd +│ │ └── ability_component.gd +│ └── ui/hud.gd +├── tools/ +│ ├── balance_sim.gd +│ └── balance_sim.tscn +├── tests/test_runner.tscn +├── tests/test_runner.gd +└── docs/ + ├── architecture.md + ├── balance-report.md + └── asset-handoff.md +``` + +`main.tscn` ist bewusst klein. `main.gd` erzeugt Karte, Baufelder und Beleuchtung; `hud.gd` erstellt die bedienbaren Controls. Die Laufzeit-Hierarchie hat folgende Grundstruktur: + +```text +Main (Node3D, main.gd) +├── World (Node3D) +│ └── Lane-, Baufeld- und Kerngeometrie, Beleuchtung +├── Camera3D (orthografische Draufsicht) +├── BattleController (Node3D) +│ └── CombatUnit (Node3D) × aktuelle Wächter und Angreifer +│ └── austauschbare Darstellung, HP-/Schildbalken, Auswahlmarkierung +└── CanvasLayer + └── HUD (Control) + └── Ressourcen, Bau-/Einheitenaktionen, Sends, Wellenbericht +``` + +`CombatUnit` wird aus dem Script erzeugt. Eine eigene `.tscn` ist dafür noch nicht nötig. Die vier Komponenten sind `RefCounted`-Objekte mit klaren Zuständigkeiten und keine zusätzlichen SceneTree-Knoten. Die Darstellung nutzt inzwischen importierte GLB-Geometrie, während Trefferpunkte, Ziele, Angriffslogik und Besitz getrennt bleiben. `AssetLibrary` fasst starre Formteile materialweise im Speicher zusammen; `AssetLibrary` lädt auch alle zehn Gegnertypen als GLB mit Gelenkgruppen. + +## Zuständigkeiten und Datenfluss + +| Baustein | Verantwortet | Schnittstelle | +| --- | --- | --- | +| `GameState` – Autoload | Phase, Wellennummer, Kern-HP, Pause, Tempo, Ergebnis und letzte Berichte | `reset_match()`, `set_phase()`, `apply_core_damage()`, `decide_winner()` | +| `EconomyManager` – Autoload | Besitz, Gold, Funken, Einkommen, Arbeiter, reservierte Sends, Rücknahmehistorie | `apply_command()`, `get_team()`, `open_build()`, `freeze()`, `settle()` | +| `WaveManager` – Autoload | Timer, Phasenübergänge, KI-Aufruf, Kampfstart und Abrechnung | `attach_battle()`, `start_match()`, `ready_for_battle()`, `advance()` | +| `AssetLibrary` – Autoload | ID-Auflösung, Icon-Cache und im Speicher zusammengefasste Modellgeometrie | `icon()`, `instantiate_model()`, `bake_mesh()` | +| `DataCatalog` – Autoload | Wächter-/Gegner-/Söldnerdefinitionen und skalierte Wellen | `get_unit()`, `get_wave()`, `get_attackers()`, `get_send()` | +| `BattleController` | Flüchtige Kampfinstanzen beider Lanes, Simulationsreihenfolge, Lecks und Prämien | `show_formation()`, `begin_battle()`, `step()` | +| `CombatUnit` | HP, Schild, Effekte, Ziel, vier Komponenten und Darstellung | `setup()`, `receive_damage()`, `heal()`, `apply_effect()`, `apply_dot()` | +| `SimpleAI` | Bauentscheidungen aus Budget, Welle und erlaubten Gegnerinformationen in zwei Stufen (Lernmodus/Standard, Dossier § 9.2) | `plan()`; benutzt dieselben Economy-Kommandos wie der Mensch | +| `Main` und `HUD` | Eingabe, Auswahl, Kamera, Anzeige | Lesen Snapshots; senden Kommandos und Bereitschaft | + +Die Autoloads machen die zentralen Dienste unabhängig vom Inhalt der aktiven Szene verfügbar. Sie ersetzen keine klare Besitzregel: Der `EconomyManager` hält den dauerhaften Einheitenbesitz; der `BattleController` hält nur die aktuelle Kampfkopie. Beim Wechsel in die nächste Bauphase entsteht die Formation erneut aus dem gespeicherten Besitz. Gefallene Wächter gehen dadurch nicht verloren. Godot beschreibt den Mechanismus in der [Dokumentation zu Autoloads](https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html). + +`DataCatalog` enthält die Einheitenwerte aus dem Dossier und getrennte Progressionen für Kurzpartie und Expedition. Basiseinheiten werden über `BASE_IDS` angeboten; eine Aufwertung wird über `upgrade_id` gefunden. Aufwertungspreise sind Zusatzkosten. Wellen skalieren Angreiferwerte beim Abruf und liefern eigenständige Dictionaries. Auch `get_team()` liefert eine tiefe Kopie: HUD oder KI können durch Änderungen an einem Snapshot keine Ressourcen erzeugen. + +## Zustandsmaschine + +```mermaid +stateDiagram-v2 + [*] --> MENU + MENU --> BUILD: Partie starten + BUILD --> COMBAT: Bereit oder Bauzeit abgelaufen / freeze + COMBAT --> RESULTS: Beide Lanes abgeschlossen / settle + RESULTS --> BUILD: 4 Sekunden oder Weiter / nächste Welle + COMBAT --> GAME_OVER: Kern zerstört oder gewählte letzte Welle abgeschlossen + GAME_OVER --> BUILD: Neue Partie / vollständiger Reset +``` + +`MENU` ist der Initial- und Reset-Zustand. Die Hauptszene kann die erste Partie direkt starten; das Eröffnungs-Overlay bietet die KI-Stufe (Lernmodus/Standard, Dossier § 3.1) und übernimmt die Auswahl in `GameState.ai_level`, das `WaveManager` bei jeder Bauphase an die KI weiterreicht. Bauzeit: 45 Sekunden in Welle 1, danach 30 Sekunden. Kämpfe enden beim Abschluss beider Lanes oder spätestens nach 90 Sekunden. Nach gewöhnlichen Wellen folgt eine viersekündige Abrechnung; die gewählte letzte Welle führt direkt zum Endergebnis. + +Nur `WaveManager` führt im normalen Spiel die Übergänge aus. Seine `_physics_process()`-Methode betreibt die Simulation mit dem Godot-Physiktakt. Bei 2× Tempo werden zwei gleich große Simulationsschritte ausgeführt. Pause verhindert den Fortschritt von Timern und Kampf, während Baukommandos in der pausierten Bauphase zulässig bleiben. + +Beim Festschreiben werden zuerst weitere Wirtschaftsänderungen gesperrt. Danach werden die Reservierungen beider Seiten gemeinsam verbindlich, Einkommen erhöht und die Send-Aufträge als Angreifer der gegenüberliegenden Lane übernommen. Erst dann startet der Kampf. Eine UI-Aktion kann somit nicht nachträglich noch den eingefrorenen Kampf verändern. + +## Wirtschaft als Kommandoschnittstelle + +Jedes Kommando hat einen Typ und nur die dazugehörigen Nutzdaten: + +```gdscript +var response: Dictionary = EconomyManager.apply_command(0, { + "type": "build", + "type_id": "g01", + "cell": Vector2i(2, 3), +}) +if not response.ok: + print(response.message) +``` + +| `type` | Weitere Felder | Wirkung | +| --- | --- | --- | +| `build` | `type_id`, `cell: Vector2i` | Freie Zelle belegen und Kaufpreis abbuchen | +| `upgrade` | `uid: int` | Aufwertung gegen Zusatzpreis, gleiche ID und Zelle | +| `sell` | `uid` | 75 % der tatsächlichen Investition, abgerundet, erstatten | +| `move` | `uid`, `cell` | Kostenlos auf freie Zelle versetzen | +| `target` | `uid`, `policy: int` | 0 = nächstes Ziel, 1 = niedrigste HP, 2 = höchste Maximal-HP | +| `worker` | keine | Nächste Preisstufe bezahlen, Arbeiter für folgende Bauphase bestellen | +| `queue_send` | `type_id` | Funken unter Vorrats-, Mengen- und Wellenbudgetgrenze reservieren | +| `cancel_send` | `index: int` | Reservierung des gewählten Auftrags freigeben | +| `undo` | keine | Letzten erfolgreichen Wirtschaftsschritt dieser Bauphase zurücknehmen | + +Die Antwort ist immer `{"ok": bool, "message": String}`. Ein abgewiesener Befehl verändert weder Ressourcen noch Rücknahmehistorie. Jede Mannschaft besitzt eine eigene Historie. Einheiten-IDs steigen auch nach Rücknahme weiter an; die IDs beider Teams haben getrennte Zahlenbereiche. + +`open_build(wave)` aktiviert bestellte Arbeiter und produziert genau einmal. `freeze(wave)` bucht die vorgemerkten Sends genau einmal ab und liefert `[aufträge_team_0, aufträge_team_1]`. `settle(team, wave, bounty)` zahlt Grundgold, das inzwischen aktuelle Einkommen und Abschussprämien genau einmal aus. Wiederholte Aufrufe derselben abgeschlossenen Transaktion sind unschädlich. Diese Sicherung verhindert doppelte Auszahlungen durch wiederholte UI-Signale oder spätere Netzwerk-Wiederholungen. + +## Kampfinstanzen und Komponenten + +`begin_battle(rosters, attackers, wave)` erhält zwei Aufstellungen und zwei Arrays skalierter Angreifer. `step(delta)` gibt einen Bericht zurück: `finished`, `elapsed`, `leak_damage`, `bounties` und `leaks`. `leak_damage` ist ausschließlich der neu entstandene Schaden dieses Schritts; Prämien und Leckzahlen sind kumulativ. Der `WaveManager` darf kumulativen Schaden daher nicht nochmals anwenden. + +| Komponente | Aufgabe | +| --- | --- | +| Bewegung | Bewegung auf der XZ-Ebene, Reichweitenabstand und lokale Trennung von Figuren | +| Zielwahl | Zielpolitik, Lane-Zugehörigkeit, Beibehaltung gültiger Ziele und stabile ID bei Gleichstand | +| Angriff | Intervall und Grundangriff; Weitergabe erfolgreicher Angriffe an Fähigkeiten | +| Fähigkeiten | Start-, Intervall- und Trefferfähigkeiten; Schaden über Zeit wird durch die Statusverwaltung der Unit fortgeführt | + +Kernschaden beider Lanes wird in einem gemeinsamen Schritt angewendet, bevor der Sieger entschieden wird. Sterben beide Kerne dabei, ist das Ergebnis unentschieden. Lecks werden einzeln als erledigt markiert und geben keine Abschussprämie. Am Timeout wird zunächst der reguläre Schritt abgearbeitet, danach werden die restlichen Angreifer als Lecks entfernt. Die Aufstellung und Investitionen bleiben erhalten. + +Die Statusverwaltung der Unit bündelt Schilde, Schaden über Zeit, Heilung und zeitlich begrenzte Effekte. Die 3×3-Schadenstypmatrix liegt an der Schadensannahme; Fähigkeiten verwenden denselben Weg. Statische Typangaben unterstützen die Prüfung der Schnittstellen im Editor; die Möglichkeiten und Grenzen beschreibt [Godots Anleitung zu statischem GDScript](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html). + +## Erweiterung zu Netzwerkspiel + +Die spätere Grenze ist bereits erkennbar: Der Client sendet Befehle mit Team, Wellennummer und Sequenz-ID; ein autoritativer Host validiert sie mit den Wirtschaftsregeln. Der Host führt Phasen und Kampf aus und verteilt freigegebene Zustandsabbilder und Ereignisse. Für den Transport müssten `Vector2i`-Zellen in einfache Zahlenpaare übersetzt und Befehle gegen doppelte Sequenz-IDs abgesichert werden. + +Die vorhandenen lokalen Methoden sind noch kein Netzwerkprotokoll. Es fehlen Verbindung, Authentifizierung, Latenzbehandlung, Wiederverbindung und Snapshot-Serialisierung. Eine stabile Zielreihenfolge und ein fester Takt helfen beim Debuggen, garantieren aber keinen plattformübergreifend deterministischen Lockstep. Autoritative Zustandsabgleiche sind deshalb die vorgesehene Erweiterung. Die KI erhält eine freigegebene gegnerische Aufstellung aus der zuletzt abgeschlossenen Bauphase; verborgene aktuelle Send-Aufträge gehören nicht zu ihren Eingaben. + +## Start und Prüfung + +`project.godot` im Godot-Projektmanager importieren und mit **F6/F5** die Hauptszene bzw. das Projekt starten. Alternativ aus dem Projektordner: + +```bash +godot --path . --editor +godot --path . +``` + +Nach Änderungen an Klassen oder beim frischen Import zunächst den Editorimport durchführen. Der Szenen-Testlauf lädt dieselben Autoloads wie das Spiel: + +```bash +godot --headless --path . --editor --quit +godot --headless --path . res://tests/test_runner.tscn +``` + +Der Testprozess meldet `PASS` und Exitcode 0 oder konkrete fehlgeschlagene Prüfungen und Exitcode 1. Die CLI-Optionen sind in [Godots Kommandozeilenanleitung](https://docs.godotengine.org/en/stable/tutorials/editor/command_line_tutorial.html) dokumentiert. + +Die Tests prüfen Wirtschaftsabrechnung und Rücknahme, Zellenbelegung, Schreibsperre im Kampf, alle neun Matrixkombinationen, einmalige Timeout-Lecks ohne Prämie, gleichzeitigen Kerntod, Reset, den Ablauf bis zum Ende von Welle 8 sowie die Verhaltensgrenzen beider KI-Stufen (Arbeiterdeckel 4/8, Send-Rhythmus, Budgetgrenzen). Komponentenprüfungen sichern drei exakte DoT-Ticks einschließlich Auffrischung ohne Zusatztreffer, Schildersetzung ohne Stapeln, den vierten Funkenlanzen-Treffer ohne rekursive Bonusangriffe und höchstens drei zusätzliche Aschenwerfer-Ziele in derselben Lane. Weitere Prüfungen kontrollieren eindeutige IDs beider Teams und Angreifer sowie die vollständige Wiederherstellung von HP, Status, Zielen und Cooldowns zwischen Wellen. Der Ablauf-Test erhöht ausschließlich in seiner Fixture die Kern-HP und setzt die Kampfzeit kurz vor das Timeout. Er prüft Zustandsübergänge und Abrechnung; er ist keine Balance-Simulation. Die ergänzende Phase-5-Abnahme simuliert drei vollständige Partien mit normalen Ressourcen; Ergebnisse und Kaufplan stehen in [phase5-balance.md](phase5-balance.md). Spielgefühl und Schwierigkeit müssen zusätzlich durch menschliche Partien beurteilt werden. + +### Balance-Sweep + +Für Wertänderungen gibt es einen deterministischen Prüfstand unter `tools/`: +zwei vollständige KI-Partien (Standard/Standard und Lernmodus/Standard) über +die produktionsidentische Wirtschaft und Kampfsimulation, ausschließlich auf +der Konsole: + +```bash +godot --headless --path . res://tools/balance_sim.tscn +``` + +Der Lauf legt pro Welle Kampfdauer, Lecks, Kernschaden, Prämien, Gold und +Wächterzahl beider Fronten aus und schlägt bei verletzten Wirtschaftsgrenzen +mit Exitcode 1 fehl. Auswertung und erste Messpunkte vom 12. September 2026 +stehen in [balance-report.md](balance-report.md). Werte im `DataCatalog` +sollten nur mit einem Vorher/Nachher-Vergleich dieses Sweeps geändert werden. + +## Phase 6 · Darstellung, Einstellungen und Release + +`AssetLibrary.instantiate_model()` bleibt der statische, nach Material zusammengefasste Weg. `instantiate_fighter()` erzeugt für Glutpakt-Figuren zwischengespeicherte Meshes pro benannter Gelenkgruppe. `animated_figure.gd` steuert ausschließlich lokale Transforms und Instanz-Trefferfarben. Neutrale Bounds und Dreieckszahlen bleiben erhalten. Die originalen `.blend`-/GLB-Einzelteile sind weiterhin editierbar. + +`Preferences` speichert Lautstärke, Stummschaltung, Kamerafolge und Vollbild per `ConfigFile`. `Soundscape` lädt 13 eigene WAVs, verwaltet zwölf Player und begrenzt Kampfgeräusche anhand echter Millisekunden. Phasenwechsel, Angriffe, Fähigkeiten und Lecks lösen Klänge aus; das Audio verändert keine Spielregeln. Tests ohne Anzeige schalten Wiedergabe ab. + +Das HUD-Optionsmenü merkt sich Pause und Tastaturfokus und stellt beide beim Schließen wieder her. Kameraorbit, freie Verschiebung und Reset liegen in `main.gd`. Gesundheitsbalken orientieren sich am Kamerabasisvektor; Boss-HP wird zusätzlich im HUD angezeigt. + +`export_presets.cfg` und `tools/build_demo.py` erzeugen eigenständige Release-Pakete mit eingebettetem PCK. Der ausdrücklich gewählte Startparameter `--smoke-test` lädt `scripts/qa/export_smoke.gd` und prüft genau das geladene Paket. Entwicklungswerkzeuge und Dokumentation sind aus dem PCK ausgeschlossen. + +## Expedition 0.8.0 + +`GameState.match_mode` bleibt über einen Neustart erhalten. `select_mode()` akzeptiert ausschließlich `short` und `expedition` im Menü oder nach Spielende; eine laufende Partie kann ihre Länge nicht wechseln. Das Menü zeigt Dauer, Bossanzahl und Wellenzahl passend zur Auswahl. + +`DataCatalog.wave_count()` liefert 8 oder 20. `get_wave()` wählt die passende Komposition, Hinweise und Skalierung. EconomyManager, WaveManager, KI und HUD verwenden diese gemeinsame Grenze: Arbeiter sind bis zur vorletzten Welle erlaubt, die KI begrenzt späte Wirtschaftsplätze und die finale Abrechnung entscheidet den HP-Sieg. Die alten Kurzpartie-Prüfungen wählen ihren Modus ausdrücklich. + +Die neue Abnahme `scripts/qa/expedition_test.gd` läuft mit `--expedition-test` auch aus dem exportierten Programm. Sie kontrolliert drei vollständige reguläre Partien, Bossfähigkeiten und Neustarts zwischen beiden Modi. Der Leistungstest unterstützt `--expedition`, um die letzte Welle bei 2× zu messen. Details: [Expeditionsbericht](../../docs/phase-08-vollstaendige-expedition.md). diff --git a/docs/asset-handoff.md b/docs/asset-handoff.md new file mode 100644 index 0000000..0e0eb26 --- /dev/null +++ b/docs/asset-handoff.md @@ -0,0 +1,76 @@ +# Saumwacht · Asset-Übergabe an die Bild-/Blender-Pipeline + +**Stand:** 15. September 2026 · verbindliche Quellen sind Dossier § 10.3 (Phase 3) und § 10.4 (Phase 4) + +Die Bildgenerierung in Phase 3 und die Blender-Pipeline in Phase 4 sind abgeschlossen. **Phase 5 bindet Glutpakt, Söldner, Arbeiter, Lane und Kerne im eigentlichen Match ein**, siehe [Slice-Bericht](../../docs/phase-05-glutpakt-slice.md). Die folgenden Übergabevorgaben dokumentieren den ursprünglichen Plan. Die aktuellen [2D-](../../docs/phase-03-asset-pipeline.md) und [3D-Lieferberichte](../../docs/phase-04-3d-pipeline.md) ergänzen diese ursprüngliche Übergabeplanung. Die 56 Icons liegen als native 1254-Pixel-PNGs vor und werden in Godot als 256-Pixel-Texturen importiert. Die 49 GLBs liegen in `assets/models/`, ihre bearbeitbaren Quellen in `assets-source/phase4/blend/`, neun eigenständige Generatoren in `assets-source/phase4/standalone/`. `assets/phase4_manifest.json` hält die geprüften Maße, Teilenamen, Dreieckszahlen und Hashes fest; 49/49 Modelle bestehen den Godot-Importtest. +Alle 46 Figuren wurden nach dem Bildvergleich neu aufgebaut; [Vergleichsgalerie](screenshots/phase4/reference-gallery.html) und [Korrekturbericht](../../docs/phase-04-icon-match.md) dokumentieren die verbleibende Vereinfachung. + +Dieses Dokument bündelt als Übergabeplan, was die Godot-Seite später +erwartet, damit die Ergebnisse ohne Nacharbeit integrierbar sind. Der laufende +Prototyp bleibt während der gesamten Zeit spielbar; seine Primitive sind der +Rückfallweg, falls einzelne Dateien fehlen. + +## Phase 3 · illustrierte Icons und UI + +Alle Vorgaben aus Dossier § 10.3 bleiben maßgeblich. Kurzfassung der +harten Anforderungen: + +| Gruppe | Anzahl | Format | Dateinamen | +| --- | ---: | --- | --- | +| Wächter-Icons | 40 | 1254 × 1254 PNG mit Alpha; 256 × 256 Godot-Import | `unit___icon.png` mit `g01`–`g10`, `m01`–`m10`, `n01`–`n10`, `w01`–`w10` | +| Söldner-Icons | 5 | gleiche Perspektive | `unit_s01…s05_icon.png`, neutrale Grenzgängerpalette | +| Ressourcen-Icons | 4 | wie oben | `res_gold`, `res_sparks`, `res_income`, `res_core` | +| Arbeiter-Icon | 1 | wie oben | `worker_funkenleser_icon.png` | +| Typensymbole | 6 | auch ohne Farbe lesbar | `type_damage_blade`, `type_damage_pierce`, `type_damage_pulse`, `type_armor_light`, `type_armor_heavy`, `type_armor_aether` | +| Lane-/Baufeldkonzept | 1 + 3 | Schrägansicht | `map_overview.png` + 3 Detailkacheln | +| UI-Elemente | 2 Rahmen, 1 Buttonfamilie | 4 Zustände, zuschneidbare Ränder | `ui_panel_a/b`, `ui_button_normal/hover/pressed/disabled` | + +- Jede Einheit erhält ein **eigenes Bild**; Sammelbilder ersetzen keine + Einzeldateien. Prüf­kriterien je Datei: Transparenz, exakte Abmessungen, + Erkennbarkeit bei 48 × 48 px. +- Gemeinsame Stilreferenz pro Fraktion (Palette aus Dossier § 6.1–6.4, + Dreiviertelansicht, Licht von links oben) sichert Konsistenz. +- Namenskonvention wie oben: kleingeschrieben, Unterstriche, ID immer am + Anfang nach dem Präfix. Die Integration wird über IDs (`type_id`) aufgelöst, + nicht über Anzeigenamen. +- Ablagevorschlag (Integration folgt in Phase 5): `saumwacht-godot/assets/icons/` + für Einheiten/Ressourcen/Typen, `saumwacht-godot/assets/ui/` für Rahmen und + Buttons. Godot importiert PNGs beim ersten Editor-Start automatisch. +- Jede Datei bekommt einen kurzen Bildinhalt-Eintrag in einer + `assets/phase3_manifest.json` (ID, Dateiname, Kurzbeschreibung), damit die + Zuordnung prüfbar bleibt und die Lizenz-/Quellenliste (Dossier § 10.4 Ende) + mitwachsen kann. + +## Phase 4 · Blender-Modelle + +Vorgaben aus Dossier § 10.4, aus Godot-Sicht zusätzlich: + +- **Export:** GLB (glTF 2.0), Y-oben (Blender-Z-oben wird beim Export + konvertiert), Ursprung jeder Figur mittig am Boden, Blickrichtung +Z. + Einheiten stehen später auf 2 × 2 m-Zellen; Zielhöhe normale Figuren + etwa 1,2–1,6 m, Bosse bis ~2,2 m (Skalierung übernimmt die Szene nicht). +- **Knoten:** getrennte Waffen-/Körperteile mit stabilen Namen + (`Body`, `Head`, `Weapon`, `ArmL`, `ArmR`, `LegL`, `LegR`), damit Treffer- + blinken und spätere Animation ohne Re-Import anbindbar bleiben. +- **Benennung:** `unit_.glb` analog den Icon-Namen; Lane-Segment, + Saumkern (2 Teamvarianten) und Funkenleser als + `map_lane_segment.glb`, `core_team0.glb`, `core_team1.glb`, `worker.glb`. +- **Materialien:** matte Standardmaterialien in den Fraktionspaletten; + keine Bildtexturen nötig. +- Ablagevorschlag: `saumwacht-godot/assets/models/`, zugehörige `.blend`- + Quellen und Kontaktbögen außerhalb von `res://` behalten oder in + `assets-source/` (Godot importiert sie nicht, wenn der Ordner eine + `.gdignore`-Datei erhält). +- Dreiecksziel: 500–1.800 (normal), bis 3.000 (Kern/Boss) — reine + Produktionsziele laut Dossier. Geliefert sind 316–1.780 Dreiecke pro Modell; + einfache Platzhalter benötigen keine künstliche Erhöhung auf 500. + +## Godot-Einbindung aus Phase 5 (umgesetzt) + +- `CombatUnit._make_visuals()` und `main.gd._make_world()` erhalten Pfad- + fallbacks: vorhanden Asset laden, sonst Primitive behalten. +- HUD-Baukarten und Inspektor bekommen die Icons per `type_id`-Lookup; + Typensymbole ergänzen Schaden-/Rüstungslinien. +- Der Asset-Manifest-Eintrag dokumentiert Integration und fehlende Dateien im + Testlauf, damit unvollständige Lieferungen auffallen, bevor sie die Szene + erreichen. diff --git a/docs/balance-report.md b/docs/balance-report.md new file mode 100644 index 0000000..e468bcb --- /dev/null +++ b/docs/balance-report.md @@ -0,0 +1,100 @@ +# Saumwacht · Balance-Bericht + +**Stand:** 12. September 2026 · Godot 4.7.2, Linux, headless · Diagnose des aktuellen Phase-2-Stands + +## Methode + +`tools/balance_sim.gd` spielt zwei KI-Duelle mit `SimpleAI`, `EconomyManager` und +`BattleController`. Die Simulation verwendet feste Startzustände und Schritte von +1/60 s. Beide Seiten erhalten die zuletzt abgeschlossene gegnerische Formation; +ihre aktuellen Aufträge bleiben verborgen. Der Lauf dauerte 11,5 s. + +Der Diagnoseablauf folgt den hier relevanten Regeln von `WaveManager`: +`natural_count` zählt ausschließlich natürliche Angreifer. Sobald ein Kern +zerstört ist, endet das Match vor einer weiteren Abrechnung. Auch wenn im selben +Schritt der letzte Angreifer verschwindet, hat das Matchende Vorrang. + +Aus dem Projektverzeichnis: + +```bash +XDG_DATA_HOME=/tmp/saumwacht-data XDG_CONFIG_HOME=/tmp/saumwacht-config XDG_CACHE_HOME=/tmp/saumwacht-cache godot --headless --path . res://tools/balance_sim.tscn +``` + +Die Tabellen zeigen Lecks einschließlich Söldnern. „Abschussprämien“ sind die im +Kampf erfassten Prämien; sie werden nur bei **Abgerechnet = Ja** ausgezahlt. +„Goldbestand“ ist der tatsächliche Vorrat am Ende der jeweiligen Tabellenzeile. +Kernschaden summiert die ausgelösten Schadensereignisse und kann beim letzten +Treffer über die verbleibenden Kern-HP hinausgehen; Kern-HP werden bei 0 begrenzt. + +## Standard gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13,3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 14,3 | 0/0 | 0/0 | 30/30 | 112/112 | 4/4 | Ja | +| 3 | 27,3 | 0/0 | 0/0 | 48/48 | 157/157 | 4/4 | Ja | +| 4 | 32,7 | 0/0 | 0/0 | 47/47 | 142/142 | 5/5 | Ja | +| 5 | 20,2 | 0/0 | 0/0 | 55/55 | 156/156 | 5/5 | Ja | +| 6 | 28,1 | 0/0 | 0/0 | 66/66 | 190/190 | 5/5 | Ja | +| 7 | 49,6 | 1/1 | 11/11 | 60/60 | 189/189 | 6/6 | Ja | +| 8 | 29,3 | 12/12 | 569/569 | 30/30 | 187/187 | 8/8 | Ja | +| 9 | 36,5 | 14/14 | 1098/1098 | 20/20 | 189/189 | 8/8 | Ja | +| 10 | 33,5 | 15/15 | 993/993 | 0/0 | 180/180 | 8/8 | Ja | +| 11 | 33,1 | 8/8 | 369/369 | 52/52 | 40/40 | 8/8 | Nein | + +**Ergebnis:** Unentschieden in Welle 11, beide Kerne bei 0 HP. Insgesamt 50 Lecks +je Front; mittlere Kampfdauer 28,9 s bis zum jeweiligen Wellen- oder Matchende. + +In diesem Lauf hielten beide Seiten Wellen 1–6 vollständig. In Welle 7 entstand +der erste Kernschaden; diese Welle dauerte mit 49,6 s am längsten. Ab Welle 8 +nahmen Lecks und Kernschaden deutlich zu. Diese Beobachtungen markieren +Situationen für spätere Formationstests und Balanceversuche. Der Lauf isoliert +weder den Einfluss der Wirtschaft noch den von Aufwertungen, Zielwahl oder Sends. + +Die tabellierten Werte beider Fronten stimmen in dieser Spiegelpartie überein. +Dies ist ein Befund für diese Ausführung und die aktuellen Eingaben, keine +plattformübergreifende Zusicherung bitidentischer Ergebnisse. + +## Lernmodus gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13,3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 23,3 | 0/0 | 0/0 | 30/30 | 177/112 | 3/4 | Ja | +| 3 | 29,5 | 7/0 | 314/0 | 12/48 | 185/156 | 3/4 | Ja | +| 4 | 21,8 | 11/0 | 360/0 | 6/44 | 170/137 | 3/5 | Ja | +| 5 | 35,5 | 2/0 | 314/0 | 18/61 | 193/166 | 4/7 | Ja | +| 6 | 31,8 | 10/0 | 472/0 | 17/60 | 158/192 | 6/7 | Ja | +| 7 | 41,7 | 7/5 | 298/217 | 24/44 | 148/173 | 6/8 | Ja | +| 8 | 31,5 | 14/11 | 757/507 | 17/27 | 144/170 | 6/8 | Ja | +| 9 | 29,7 | 7/0 | 498/0 | 0/13 | 9/10 | 7/9 | Nein | + +**Ergebnis:** Standard gewinnt in Welle 9 mit 2.276 Kern-HP. Der Lernmodus endet +bei 0 HP. Insgesamt 58/16 Lecks; mittlere Kampfdauer 28,7 s. + +Der Lernmodus erlitt in dieser Partie ab Welle 3 Lecks, Standard erstmals in +Welle 7. Die letzte Tabellenzeile zeigt den Moment des Matchendes; die andere +Front muss dann nicht vollständig geklärt sein. Insbesondere bedeutet die 0 bei +Standard-Lecks in Welle 9 nicht, dass diese Front die ganze Welle gehalten hätte. +Aus diesem einzelnen Duell lässt sich weder eine Erfolgsquote der KI-Stufen noch +eine passende Schwierigkeit für menschliche Spieler ableiten. + +## Geprüfter Umfang und Grenzen + +Der Lauf endete mit Exit-Code 0 und meldete keine Verletzung der überprüften +Invarianten: Gold/Funken nicht negativ, Funkenobergrenze 400, maximal 8 Arbeiter +einschließlich Bestellungen, gültige eindeutige Zellbelegung im 6 × 8 Baufeld, +maximal 8 Sends und Einhaltung von Sendbudget und vorhandenen Funken. Beide +Partien erreichten ein Matchende innerhalb von 20 Wellen; kein beobachteter Kampf +überschritt 90 s. + +Diese Prüfungen decken die während der zwei Partien besuchten Zustände ab. Sie +ersetzen keine gezielten Tests für Undo, Schadensmatrix, Fähigkeiten, Timeout +oder alle Siegpfade. Wellen nach dem jeweiligen Matchende wurden nicht gespielt. +Die Mechanik wird hier diagnostiziert; es wurden keine Balancewerte verändert. + +Für die Balancearbeit in Phase 5 werden mehrere Formationen, andere Kauf- und +Sendpläne sowie menschliche Spieltests benötigt. Vor allem Ausgaben, Armeewert, +Arbeiterinvestitionen und kumuliertes Einkommen müssten zusätzlich erfasst +werden, um wirtschaftliches Schneeballen zu beurteilen. Der verbleibende +Goldvorrat allein beantwortet diese Frage nicht. diff --git a/docs/compare-godot.json b/docs/compare-godot.json new file mode 100644 index 0000000..96a408c --- /dev/null +++ b/docs/compare-godot.json @@ -0,0 +1,125 @@ +{ + "camera": { + "closeup": { + "look_at": [ + 0.1, + 0.95, + 0.2 + ], + "position": [ + 1.4, + 1.5, + 2.4 + ], + "size": 2.4 + }, + "game": { + "look_at": [ + 0, + 0.5, + 0 + ], + "position": [ + 1.5, + 10.5, + 9.5 + ], + "size": 7.0, + "yaw": 0.2 + }, + "projection": "orthogonal" + }, + "captures": [ + "closeup", + "game-camera", + "move-00", + "move-12", + "move-24", + "move-end" + ], + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "Godot 4.7.2-stable (fedora)", + "lighting": { + "fill": { + "color": "#a8c4e8", + "energy": 0.55, + "rotation_degrees": [ + -35, + 150, + 0 + ] + }, + "key": { + "color": "#ffd4a0", + "energy": 1.7, + "rotation_degrees": [ + -48, + -36, + 0 + ] + }, + "tonemap": "ACES" + }, + "msaa": "4x", + "renderer": "forward_plus", + "results": [ + { + "draw_calls": 49.0, + "fps": 809.200015085933, + "instances": 1, + "mean_frame_ms": 1.23578840998144, + "p95_frame_ms": 1.75, + "resolution": "(1920, 1080)", + "video_memory_bytes": 619950352.0 + }, + { + "draw_calls": 708.0, + "fps": 654.710968775551, + "instances": 30, + "mean_frame_ms": 1.52739154786151, + "p95_frame_ms": 1.982, + "resolution": "(1920, 1080)", + "video_memory_bytes": 638344640.0 + }, + { + "draw_calls": 2058.0, + "fps": 269.196491783343, + "instances": 90, + "mean_frame_ms": 3.71475866336634, + "p95_frame_ms": 4.582, + "resolution": "(1920, 1080)", + "video_memory_bytes": 676952960.0 + }, + { + "draw_calls": 49.0, + "fps": 544.939142350141, + "instances": 1, + "mean_frame_ms": 1.83506729886815, + "p95_frame_ms": 2.624, + "resolution": "(2560, 1440)", + "video_memory_bytes": 813986064.0 + }, + { + "draw_calls": 708.0, + "fps": 468.227458198323, + "instances": 30, + "mean_frame_ms": 2.13571413314347, + "p95_frame_ms": 2.947, + "resolution": "(2560, 1440)", + "video_memory_bytes": 832380352.0 + }, + { + "draw_calls": 2058.0, + "fps": 250.669006244058, + "instances": 90, + "mean_frame_ms": 3.98932446808511, + "p95_frame_ms": 5.223, + "resolution": "(2560, 1440)", + "video_memory_bytes": 870988672.0 + } + ], + "sample_seconds": 6, + "scope": "Comparison stage: pattern figure, worker, core, rock, tree, arena tile. Not a full match.", + "vsync": false, + "warmup_seconds": 2 +} \ No newline at end of file diff --git a/docs/phase10-QA.md b/docs/phase10-QA.md new file mode 100644 index 0000000..32f65d1 --- /dev/null +++ b/docs/phase10-QA.md @@ -0,0 +1,73 @@ +# Die grüne Kluft · Demo 0.10.0 + +Stand: **19. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. Finale Pakete verwenden das offizielle Release-Template `ed1daf0bf`. + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Quellprojekt: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Quellprojekt mit Grafikausgabe und Kampfaufnahmen | 1.684 bestanden | +| Entpacktes Linux-Paket: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Entpacktes Linux-Paket: vollständiger Grafiklauf bis Welle 20 | 1.684 bestanden | +| Windows-PCK mit Linux-Godot: gleiche Prüfung | 1.665 bestanden | +| Beide Pakete: Kurzpartie, Assets, Audio, Modellbetrachter und Optionen | jeweils 274 bestanden | +| Entpacktes Linux-Paket: Vulkan-Bedienprüfung | 128 bestanden | +| Beiliegendes Linux-Kompatibilitätsskript: OpenGL-Bedienprüfung | 128 bestanden | +| Wurzelbund-Endkampf bei 2×, Fokus, Kamera und Audio | 9 bestanden | +| GLB-Geometrie | 59/59 bestanden, keine Fehler oder Topologiewarnungen | +| Godot-Modellimport | 59/59 bestanden | +| Eigenständige Blender-Skripte außerhalb des Projekts | 9/9 bestanden; fremde Szene und Daten erhalten | +| Wiederholter Modellbau mit Szenenerhalt und native Blender-Datei | bestanden | +| Archive, extrahierte Programme und Schriftlizenz | CRC, SHA-256 und Inhalte geprüft | +| Nativer Windows-Lauf | Nicht durchgeführt | + +Alle genannten Spielprüfungen enden ohne fehlgeschlagene Checks. Die Pakete wurden außerhalb des Quellprojekts unter `/tmp/saumwacht-010-package-check` gestartet. Separate temporäre Benutzerordner schützen vorhandene Spieleinstellungen. + +## Grafik und Bedienung + +Der Test prüft die instanzierte Landschaft samt Wasser, beide nativen 4096 × 4096 Materialkarten sowie das Ein- und Ausklappen der Bauleiste beim Phasenwechsel. Die Modelle behalten ihre beweglichen Teile. Die neue Landschaft verändert weder Bauzellen noch Spielregeln. + +Die echte Mauseingabe platziert einen Wächter auf einem sichtbaren Feld. Auswahl, Vorschauabbau, Aufwertung ohne Scrollen, C-Basiswechsel, neue Partie, Fraktionswechsel und beide Starter bestehen weiter. Wichtige Schaltflächen bleiben bei 1152 × 720 sichtbar; acht Söldner-Chips scrollen horizontal. Manuelle Bauphase und Abrechnung warten auf Eingabe, auch nach 120 simulierten Sekunden. Der optionale Timer bleibt funktionsfähig. + +Arbeiter produzieren ab der nächsten Bauphase und können vorher vollständig zurückgenommen werden. Fraktionsfremde Käufe sind abgewiesen; freie Funken und Söldnerreservierungen stimmen überein. Tests für Optionspause, Fokus, Modellansicht und Kamera bleiben erhalten. + +**Die Tests bestätigen Funktion und technische Integrität, nicht die gewünschte künstlerische Endqualität.** Figuren besitzen weiterhin starre Gelenkanimationen. Die neue Anforderung an detaillierte Skelettanimationen und ausgearbeitete Charakterformen ist in der [Engine-Prüfung und Qualitätsvorgabe](../../docs/engine-pruefung-2026-09-19.md) festgehalten und noch nicht umgesetzt. + +## Fähigkeiten und Partien + +Geprüft werden unter anderem Heilungszielwahl, volle HP ohne verbrauchten Cooldown, Takt und Reichweite, Lane-Trennung, Heilungsreduktion, wiederholte Treffer, getrennte Brandfamilien, Bossverlangsamung, Effektablauf und Flächenschadengrenzen. Isolierte Fähigkeitstests setzen ihre Fixtures gezielt; vollständige Partien verwenden ausschließlich normale bezahlte Wirtschaftskommandos. + +| Reguläres Duell | Letzte Welle | Kern-HP | +| --- | ---: | ---: | +| Wurzelbund → Glutpakt | 20 | 1.244 / 1.709 | +| Glutpakt → Wurzelbund | 20 | 1.709 / 1.244 | +| Wurzelbund → Wurzelbund | 20 | 1.244 / 1.244 | +| Wurzelbund-Spiegel, Kurzpartie | 8 | 3.000 / 3.000 | + +Diese Ergebnisse entsprechen der vorherigen Version. Sie ersetzen keine Balanceprüfung mit menschlichen Strategien. + +## Laufzeit + +Wurzelbund-Spiegel, Welle 20, 86 Kampfinstanzen, 2× Tempo, 1600 × 960. Zwölf Sekunden nach zwei Sekunden Aufwärmen: **143,83 FPS im Mittel**, **6,95 ms mittlere Framezeit**, **12,15 ms im 95. Perzentil**, maximal 5.064 Draw Calls und 120 Audioereignisse. Die Messung lief ohne parallelen Blender-Bau oder andere Spielprüfung. Lokale RTX-5060-Ti-Messung mit Forward+ und VSync, keine zugesicherte Leistung auf anderen Geräten oder bei 4K. [Messdaten](phase10-runtime.json). + +## Nachweise und Wiederholung + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . -- --faction-test +godot --path . -- --faction-test --ui-only +godot --headless --path . -- --smoke-test +godot --path . res://tools/verify_phase6_runtime.tscn -- --expedition --wurzelbund --phase10 +python3 tools/verify_phase4_glb.py --json +godot --headless --path . --script res://tools/verify_phase4_models.gd +``` + +[Paketintegrität](phase10-package-check.json) · [Linux-Partien](phase10-package-linux.json) · [Windows-PCK-Partien](phase10-package-windows.json) · [Vulkan-UI](phase10-package-vulkan.json) · [OpenGL-UI](phase10-package-opengl.json) · [GLB-Audit](phase10-glb-audit.json) · [Quellprojekt](phase10-verification.json) · [Protokolle](phase10-logs/). + +Aufnahmen der entpackten Demo: [Menü](screenshots/phase10/menu-package.png), [Bauen](screenshots/phase10/build-package.png), [Basis](screenshots/phase10/base-package.png), [Auswahl](screenshots/phase10/selection.png), [Wirtschaft](screenshots/phase10/economy.png), [Mindestfenstergröße](screenshots/phase10/minimum-window.png). Größere tatsächliche Godot-Ansichten: [Arena](screenshots/phase10/map-overview.png), [Ringborke](screenshots/phase10/model-w04.png). + +Der vollständige Grafiklauf der entpackten Linux-Demo besteht **1.684 Checks**. [Ergebnis](phase10-package-full-visual.json), [Welle 5](screenshots/phase10/wave-05.png), [Welle 10](screenshots/phase10/wave-10.png), [Welle 15](screenshots/phase10/wave-15.png), [Welle 20](screenshots/phase10/wave-20.png). Die späten Kampfansichten und die Mindestfenstergröße wurden zusätzlich visuell kontrolliert. + +Blender meldet auf diesem Rechner eine OCIO-Konfigurationsversionsabweichung und fehlende optionale Draco-/Meshoptimizer-Bibliotheken. Der Modellbau nutzt die funktionierende Farbkonfigurationsrückfallebene und unkomprimierte GLBs; die abschließenden Geometrie- und Importprüfungen bestehen. Der Editor-Export meldet in der Sandbox einen nicht verfügbaren TCP-Debugport, beide Exporte enden erfolgreich. Finale Release-Prüfungen melden keine Skript- oder Shaderfehler. + +[Start und Pakete](phase10-builds.md) · [Grafikänderungen](../../docs/phase-10-grafik-und-landschaft.md) · [Historische Prüfung 0.9.0](phase9-QA.md). diff --git a/docs/phase10-art-assets.json b/docs/phase10-art-assets.json new file mode 100644 index 0000000..af702d4 --- /dev/null +++ b/docs/phase10-art-assets.json @@ -0,0 +1,250 @@ +{ + "environment": { + "name": "Die grüne Kluft", + "source_objects": 2586, + "runtime_chunks": 62, + "triangles": 1607600, + "seed": 10092026, + "blender": "5.2.1 LTS", + "sha256": "bebe2d4193500df1cf54970adf0e240607430d66e42fd9ab2e67368166a6d052", + "playable_grids": 2, + "cell_size_m": 2, + "grid_cells": [ + 6, + 8 + ] + }, + "sculpt_assets": [ + { + "id": "g01", + "name": "Kohlenbeißer", + "runtime_triangles": 79780, + "offline_render_triangles": 641050, + "sculpt_parts": 18 + }, + { + "id": "g02", + "name": "Schlackenklaue", + "runtime_triangles": 75624, + "offline_render_triangles": 549234, + "sculpt_parts": 18 + }, + { + "id": "g03", + "name": "Schlackenwacht", + "runtime_triangles": 67232, + "offline_render_triangles": 565982, + "sculpt_parts": 18 + }, + { + "id": "g04", + "name": "Basaltbastion", + "runtime_triangles": 80764, + "offline_render_triangles": 470044, + "sculpt_parts": 18 + }, + { + "id": "g05", + "name": "Funkenlanze", + "runtime_triangles": 54710, + "offline_render_triangles": 382610, + "sculpt_parts": 12 + }, + { + "id": "g06", + "name": "Glasballiste", + "runtime_triangles": 38036, + "offline_render_triangles": 261386, + "sculpt_parts": 10 + }, + { + "id": "g07", + "name": "Aschenwerfer", + "runtime_triangles": 81492, + "offline_render_triangles": 687762, + "sculpt_parts": 18 + }, + { + "id": "g08", + "name": "Kraterrufer", + "runtime_triangles": 77130, + "offline_render_triangles": 683400, + "sculpt_parts": 18 + }, + { + "id": "g09", + "name": "Herdhüter", + "runtime_triangles": 84568, + "offline_render_triangles": 685558, + "sculpt_parts": 18 + }, + { + "id": "g10", + "name": "Sonnenesse", + "runtime_triangles": 96706, + "offline_render_triangles": 697696, + "sculpt_parts": 18 + }, + { + "id": "w01", + "name": "Dornhopser", + "runtime_triangles": 61376, + "offline_render_triangles": 695666, + "sculpt_parts": 18 + }, + { + "id": "w02", + "name": "Rankenschnapper", + "runtime_triangles": 78020, + "offline_render_triangles": 810680, + "sculpt_parts": 15 + }, + { + "id": "w03", + "name": "Korkrücken", + "runtime_triangles": 84786, + "offline_render_triangles": 782076, + "sculpt_parts": 18 + }, + { + "id": "w04", + "name": "Ringborke", + "runtime_triangles": 134530, + "offline_render_triangles": 872260, + "sculpt_parts": 18 + }, + { + "id": "w05", + "name": "Samenschleuder", + "runtime_triangles": 50536, + "offline_render_triangles": 493876, + "sculpt_parts": 14 + }, + { + "id": "w06", + "name": "Zapfenkrone", + "runtime_triangles": 62588, + "offline_render_triangles": 561488, + "sculpt_parts": 16 + }, + { + "id": "w07", + "name": "Sporenkelch", + "runtime_triangles": 69164, + "offline_render_triangles": 534224, + "sculpt_parts": 9 + }, + { + "id": "w08", + "name": "Pilzkathedrale", + "runtime_triangles": 103748, + "offline_render_triangles": 624368, + "sculpt_parts": 11 + }, + { + "id": "w09", + "name": "Tauhüter", + "runtime_triangles": 52040, + "offline_render_triangles": 489320, + "sculpt_parts": 8 + }, + { + "id": "w10", + "name": "Quellgeflecht", + "runtime_triangles": 61052, + "offline_render_triangles": 475052, + "sculpt_parts": 12 + }, + { + "id": "worker", + "name": "Funkenleser", + "runtime_triangles": 24026, + "offline_render_triangles": 103466, + "sculpt_parts": 6 + }, + { + "id": "core_team0", + "name": "Saumkern · Team 0", + "runtime_triangles": 36652, + "offline_render_triangles": 344572, + "sculpt_parts": 16 + }, + { + "id": "core_team1", + "name": "Saumkern · Team 1", + "runtime_triangles": 36848, + "offline_render_triangles": 344768, + "sculpt_parts": 16 + }, + { + "id": "e01", + "name": "Splitterling", + "runtime_triangles": 19228, + "offline_render_triangles": 166318, + "sculpt_parts": 9 + }, + { + "id": "e02", + "name": "Schalenläufer", + "runtime_triangles": 20180, + "offline_render_triangles": 167270, + "sculpt_parts": 9 + }, + { + "id": "e03", + "name": "Nebelrest", + "runtime_triangles": 35898, + "offline_render_triangles": 299628, + "sculpt_parts": 9 + }, + { + "id": "e04", + "name": "Fadenschütze", + "runtime_triangles": 51050, + "offline_render_triangles": 353780, + "sculpt_parts": 10 + }, + { + "id": "e05", + "name": "Bruchstampfer", + "runtime_triangles": 62798, + "offline_render_triangles": 482828, + "sculpt_parts": 18 + }, + { + "id": "e06", + "name": "Knotenrufer", + "runtime_triangles": 48336, + "offline_render_triangles": 432966, + "sculpt_parts": 12 + }, + { + "id": "e07", + "name": "Bruchhirsch", + "runtime_triangles": 33800, + "offline_render_triangles": 388220, + "sculpt_parts": 10 + }, + { + "id": "e08", + "name": "Riegelkoloss", + "runtime_triangles": 81240, + "offline_render_triangles": 470520, + "sculpt_parts": 18 + }, + { + "id": "e09", + "name": "Maskenrichter", + "runtime_triangles": 57310, + "offline_render_triangles": 441940, + "sculpt_parts": 12 + }, + { + "id": "e10", + "name": "Schlundkrone", + "runtime_triangles": 64694, + "offline_render_triangles": 708914, + "sculpt_parts": 18 + } + ] +} diff --git a/docs/phase10-builds.md b/docs/phase10-builds.md new file mode 100644 index 0000000..ec70f9b --- /dev/null +++ b/docs/phase10-builds.md @@ -0,0 +1,53 @@ +# Demo 0.10.0 · Windows und Linux + +Stand: 19. September 2026. Enthalten: Glutpakt, Wurzelbund, 8/20 Wellen, Rivalen-KI, neue Ruinenlandschaft, detailliertere Figuren und Materialien sowie das überarbeitete Interface. + +| System | Paket | Größe | +| --- | --- | ---: | +| Windows | [Saumwacht-Windows-x64-0.10.0.zip](../../dist/Saumwacht-Windows-x64-0.10.0.zip) | 184,3 MiB | +| Linux | [Saumwacht-Linux-x64-0.10.0.zip](../../dist/Saumwacht-Linux-x64-0.10.0.zip) | 174,8 MiB | + +ZIP vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh` oder `Saumwacht.x86_64`. Godot und Blender werden zum Spielen nicht benötigt. Spieldaten sind im Programm eingebettet. Beide Archive enthalten eine Anleitung, Lizenzen einschließlich Cantarell-Schrift und einen OpenGL-Kompatibilitätsstart. Ältere versionierte ZIPs bleiben erhalten. + +Wurzelbund ist vorausgewählt. Die Startformation kauft drei Wächter für 185 Gold; beim Glutpakt kostet sie 180 Gold. Bauphase und Abrechnung warten auf die Leertaste. C wechselt zur Basis und zurück. F1 öffnet Optionen und den Neustart zur Fraktionsauswahl. Während des Kampfes geben eingeklappte Baukarten mehr Sicht auf die Arena frei. + +## Paketprüfung + +Beide Archive bestehen CRC- und SHA-256-Prüfung. Die Hashes der extrahierten Programme stimmen mit dem Buildmanifest überein. Alle folgenden Prüfungen liefen außerhalb des Quellprojekts: + +- Linux: **1.665** Fraktions-/Bedien-/Matchprüfungen und **274** Kurzpartie-/Asset-/Audio-/Optionsprüfungen, keine Fehler. +- Windows-Spieldaten mit Linux-Godot: ebenfalls **1.665 + 274**, keine Fehler. +- Entpacktes Linux-Programm mit Vulkan: **128** Bedienprüfungen, einschließlich echter Mauseingabe und Mindestfenstergröße 1152 × 720. +- Beiliegendes Linux-Kompatibilitätsskript mit OpenGL: ebenfalls **128**, keine Fehler. +- Entpackte Linux-Demo mit vollständiger Grafikausgabe bis Welle 20: **1.684** Checks, keine Fehler. [Ergebnis und Renderer](phase10-package-full-visual.json). + +**Ein nativer Windows-Lauf wurde nicht durchgeführt.** Die Windows-Ausgabe ist ein nicht signiertes x86-64-Programm. Der PCK-Test bestätigt Spieldaten und Skripte, nicht Windows-Start, Treiber oder Audiogeräte. + +[Paketnachweis](phase10-package-check.json) · [Linux-Prüfung](phase10-package-linux.json) · [Windows-PCK](phase10-package-windows.json) · [Vulkan](phase10-package-vulkan.json) · [OpenGL](phase10-package-opengl.json) · [QA](QA.md). + +## Reproduzieren + +`python3 tools/build_demo.py` aus `saumwacht-godot` nutzt die vorhandenen offiziellen Godot-4.7.2-Release-Templates. Der Builder aktualisiert die versionierten Archive, `dist/build-manifest.json`, `dist/SHA256SUMS.txt` und die entpackten Ordner `dist/linux` und `dist/windows`. Quellen, Dokumentation und Entwicklungswerkzeuge sind vom Export ausgeschlossen; dynamisch geladene Spieldaten sind eingeschlossen. + +```bash +# Aus einem Ordner außerhalb des Quellprojekts: +/path/to/Saumwacht.x86_64 --headless -- --faction-test +/path/to/Saumwacht.x86_64 -- --faction-test --ui-only +bash /path/to/Kompatibilitaet.sh -- --faction-test --ui-only +/path/to/Saumwacht.x86_64 --headless -- --smoke-test + +# Windows-Spieldaten; ausdrücklich kein Windows-Prozess: +godot --headless --main-pack /path/to/Saumwacht.exe -- --faction-test +godot --headless --main-pack /path/to/Saumwacht.exe -- --smoke-test +``` + +Die Fensterüberschrift lautet „Saumwacht · Die grüne Kluft“. Der historische Benutzerordner `Saumwacht · Glutpakt` bleibt für vorhandene Einstellungen bestehen. Bei automatischen Prüfungen separate `XDG_DATA_HOME`- und `XDG_CONFIG_HOME`-Verzeichnisse verwenden. + +## SHA-256 + +```text +a2d60a5e5947575899045b99a0f27a549e2f71539014591210db0c978c492ccb Saumwacht-Linux-x64-0.10.0.zip +4f0d3b46d9ded5091644da2c7306694d55712f9c2d015ecc796b7ecc0d9c5985 Saumwacht-Windows-x64-0.10.0.zip +``` + +[Grafikbericht und Blender-Quellen](../../docs/phase-10-grafik-und-landschaft.md) · [Engine-Prüfung und nächste Modellqualität](../../docs/engine-pruefung-2026-09-19.md). diff --git a/docs/phase10-glb-audit.json b/docs/phase10-glb-audit.json new file mode 100644 index 0000000..8810da0 --- /dev/null +++ b/docs/phase10-glb-audit.json @@ -0,0 +1,7981 @@ +{ + "asset_count": 59, + "errors": [], + "assets": [ + { + "id": "g01", + "file": "unit_g01.glb", + "errors": [], + "warnings": [], + "triangles": 79780, + "mesh_parts": 131, + "primitives": 131, + "vertices": 51202, + "closed_meshes": 131, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g02", + "file": "unit_g02.glb", + "errors": [], + "warnings": [], + "triangles": 75624, + "mesh_parts": 133, + "primitives": 133, + "vertices": 49708, + "closed_meshes": 133, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g03", + "file": "unit_g03.glb", + "errors": [], + "warnings": [], + "triangles": 67232, + "mesh_parts": 119, + "primitives": 119, + "vertices": 41938, + "closed_meshes": 119, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g04", + "file": "unit_g04.glb", + "errors": [], + "warnings": [], + "triangles": 80764, + "mesh_parts": 220, + "primitives": 220, + "vertices": 54069, + "closed_meshes": 220, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g05", + "file": "unit_g05.glb", + "errors": [], + "warnings": [], + "triangles": 54710, + "mesh_parts": 118, + "primitives": 118, + "vertices": 35392, + "closed_meshes": 118, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderFin", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderFin", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ChestStoneL", + "Body_ChestStoneR", + "Body_CuirassL", + "Body_CuirassR", + "Body_EmberHeart", + "Body_Spine", + "Head_Crest", + "Head_Helmet", + "Head_Neck", + "Head_Visor", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar10", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceEmber", + "Weapon_LanceShaft", + "Weapon_SpearEdge1", + "Weapon_SpearEdge_1", + "Weapon_SpearHead" + ] + }, + { + "id": "g06", + "file": "unit_g06.glb", + "errors": [], + "warnings": [], + "triangles": 38036, + "mesh_parts": 85, + "primitives": 85, + "vertices": 23398, + "closed_meshes": 85, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrankInsetL", + "Body_CrankInsetR", + "Body_CrankL", + "Body_CrankR", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Body_Gearbox", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoltHead", + "Weapon_CentralBolt", + "Weapon_DrawCableL", + "Weapon_DrawCableR", + "Weapon_GlassLimbL", + "Weapon_GlassLimbR", + "Weapon_LimbClampL", + "Weapon_LimbClampR", + "Weapon_LimbEdgeL", + "Weapon_LimbEdgeR", + "Weapon_RailL", + "Weapon_RailR", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5", + "Weapon_RailTrimL", + "Weapon_RailTrimR", + "Weapon_RearHousing", + "Weapon_RearTrim" + ] + }, + { + "id": "g07", + "file": "unit_g07.glb", + "errors": [], + "warnings": [], + "triangles": 81492, + "mesh_parts": 128, + "primitives": 128, + "vertices": 53594, + "closed_meshes": 128, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "Weapon_EmberBoulder", + "Weapon_LavaPool" + ] + }, + { + "id": "g08", + "file": "unit_g08.glb", + "errors": [], + "warnings": [], + "triangles": 77130, + "mesh_parts": 123, + "primitives": 123, + "vertices": 48878, + "closed_meshes": 123, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "Weapon_LavaPool" + ] + }, + { + "id": "g09", + "file": "unit_g09.glb", + "errors": [], + "warnings": [], + "triangles": 84568, + "mesh_parts": 173, + "primitives": 173, + "vertices": 51374, + "closed_meshes": 173, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone10", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_HearthBack", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Body_OvenDark", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Head_Chimney", + "Head_ChimneyCap", + "Head_ChimneyRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "g10", + "file": "unit_g10.glb", + "errors": [], + "warnings": [], + "triangles": 96706, + "mesh_parts": 223, + "primitives": 223, + "vertices": 58942, + "closed_meshes": 223, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_HearthBack", + "Body_MantleL", + "Body_MantleR", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_OvenDark", + "Body_SolarStream", + "Body_SunFrame", + "Body_SunHeart", + "Body_SunSocket", + "Body_TabardL", + "Body_TabardR", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "m01", + "file": "unit_m01.glb", + "errors": [], + "warnings": [], + "triangles": 1284, + "mesh_parts": 42, + "primitives": 42, + "vertices": 2424, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Upper", + "Body_Belt", + "Body_Chimney", + "Body_ChimneyLip", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_PressureGauge", + "Body_RoundKettle", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m02", + "file": "unit_m02.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2552, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Pauldron", + "ArmL_Shield_Face", + "ArmL_Shield_Rim", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Pauldron", + "ArmR_Shield_Face", + "ArmR_Shield_Rim", + "ArmR_Upper", + "Body_CeramicChest_Face", + "Body_CeramicChest_Rim", + "Body_HeavyChest", + "Body_PressureTankL", + "Body_PressureTankR", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemL", + "Body_ValveStemR", + "Body_ValveWheelL", + "Body_ValveWheelR", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m03", + "file": "unit_m03.glb", + "errors": [], + "warnings": [], + "triangles": 932, + "mesh_parts": 43, + "primitives": 43, + "vertices": 1776, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ] + }, + { + "id": "m04", + "file": "unit_m04.glb", + "errors": [], + "warnings": [], + "triangles": 1398, + "mesh_parts": 60, + "primitives": 60, + "vertices": 2600, + "closed_meshes": 60, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "ArmL1_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "ArmL2_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "ArmR1_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "ArmR2_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL1_Blade0", + "WeaponL2_Blade0", + "WeaponR0_Blade0", + "WeaponR1_Blade0", + "WeaponR2_Blade0" + ] + }, + { + "id": "m05", + "file": "unit_m05.glb", + "errors": [], + "warnings": [], + "triangles": 1148, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2192, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Head_Scope", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m06", + "file": "unit_m06.glb", + "errors": [], + "warnings": [], + "triangles": 1432, + "mesh_parts": 66, + "primitives": 66, + "vertices": 2730, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m07", + "file": "unit_m07.glb", + "errors": [], + "warnings": [], + "triangles": 740, + "mesh_parts": 27, + "primitives": 27, + "vertices": 1403, + "closed_meshes": 27, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_ResonatorHousing0", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston" + ] + }, + { + "id": "m08", + "file": "unit_m08.glb", + "errors": [], + "warnings": [], + "triangles": 1316, + "mesh_parts": 50, + "primitives": 50, + "vertices": 2464, + "closed_meshes": 50, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_HousingLatch1_1", + "Body_HousingLatch1__1", + "Body_ResonatorHousing0", + "Body_ResonatorHousing1", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_DiscPiston0", + "Weapon_DiscPiston1", + "Weapon_ImpactDisc0", + "Weapon_ImpactDisc1" + ] + }, + { + "id": "m09", + "file": "unit_m09.glb", + "errors": [], + "warnings": [], + "triangles": 1160, + "mesh_parts": 51, + "primitives": 51, + "vertices": 2146, + "closed_meshes": 51, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_PendulumBob", + "Body_PendulumStem", + "Body_Waist", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "m10", + "file": "unit_m10.glb", + "errors": [], + "warnings": [], + "triangles": 946, + "mesh_parts": 49, + "primitives": 49, + "vertices": 1828, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Upper", + "Body_Coat", + "Body_CoatGoldL", + "Body_CoatGoldR", + "Body_CreamStoleL", + "Body_CreamStoleR", + "Body_PendulumBob", + "Body_PendulumOpening", + "Body_PendulumStem", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "n01", + "file": "unit_n01.glb", + "errors": [], + "warnings": [], + "triangles": 1132, + "mesh_parts": 16, + "primitives": 16, + "vertices": 3232, + "closed_meshes": 16, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Claw", + "WeaponR_Claw" + ] + }, + { + "id": "n02", + "file": "unit_n02.glb", + "errors": [], + "warnings": [], + "triangles": 1156, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3304, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1" + ] + }, + { + "id": "n03", + "file": "unit_n03.glb", + "errors": [], + "warnings": [], + "triangles": 934, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2688, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Sickle", + "WeaponR_Sickle" + ] + }, + { + "id": "n04", + "file": "unit_n04.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3932, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CrescentCrown", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_ShearLoopLower", + "Weapon_ShearLoopUpper", + "Weapon_ShearLower", + "Weapon_ShearPivot", + "Weapon_ShearUpper" + ] + }, + { + "id": "n05", + "file": "unit_n05.glb", + "errors": [], + "warnings": [], + "triangles": 1118, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2986, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip" + ] + }, + { + "id": "n06", + "file": "unit_n06.glb", + "errors": [], + "warnings": [], + "triangles": 1498, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3844, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_HornArchL", + "Weapon_HornArchR", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ] + }, + { + "id": "n07", + "file": "unit_n07.glb", + "errors": [], + "warnings": [], + "triangles": 1274, + "mesh_parts": 15, + "primitives": 15, + "vertices": 3354, + "closed_meshes": 15, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_BellRim", + "Weapon_Clapper", + "Weapon_ClapperStem", + "Weapon_HangingBell" + ] + }, + { + "id": "n08", + "file": "unit_n08.glb", + "errors": [], + "warnings": [], + "triangles": 1482, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3958, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Sickle", + "ArmR_Sickle", + "Body_ArchMask", + "Body_ArchMask_Eye1", + "Body_ArchMask_Eye_1", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Body_CathedralShell", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CentralSpire", + "Head_SpireL", + "Head_SpireR", + "Weapon_Clapper", + "Weapon_ClapperChain" + ] + }, + { + "id": "n09", + "file": "unit_n09.glb", + "errors": [], + "warnings": [], + "triangles": 1314, + "mesh_parts": 24, + "primitives": 24, + "vertices": 3740, + "closed_meshes": 24, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "n10", + "file": "unit_n10.glb", + "errors": [], + "warnings": [], + "triangles": 1734, + "mesh_parts": 40, + "primitives": 40, + "vertices": 4872, + "closed_meshes": 40, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirHorn1_1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn2_1", + "Head_ChoirHorn2__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Mouth", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp0", + "Head_ChoirWisp1", + "Head_ChoirWisp2", + "Head_CurledHood", + "Head_GreatHorn1", + "Head_GreatHorn_1", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "w01", + "file": "unit_w01.glb", + "errors": [], + "warnings": [], + "triangles": 61376, + "mesh_parts": 166, + "primitives": 166, + "vertices": 31462, + "closed_meshes": 166, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Bark0", + "Body_Bark0_Fissure0", + "Body_Bark0_Fissure1", + "Body_Bark0_Fissure2", + "Body_Bark0_Fissure3", + "Body_Bark1", + "Body_Bark1_Fissure0", + "Body_Bark1_Fissure1", + "Body_Bark1_Fissure2", + "Body_Bark1_Fissure3", + "Body_Bark2", + "Body_Bark2_Fissure0", + "Body_Bark2_Fissure1", + "Body_Bark2_Fissure2", + "Body_Bark2_Fissure3", + "Body_Bark3", + "Body_Bark3_Fissure0", + "Body_Bark3_Fissure1", + "Body_Bark3_Fissure2", + "Body_Bark3_Fissure3", + "Body_Bark4", + "Body_Bark4_Fissure0", + "Body_Bark4_Fissure1", + "Body_Bark4_Fissure2", + "Body_Bark4_Fissure3", + "Body_Bark5", + "Body_Bark5_Fissure0", + "Body_Bark5_Fissure1", + "Body_Bark5_Fissure2", + "Body_Bark5_Fissure3", + "Body_Bark6", + "Body_Bark6_Fissure0", + "Body_Bark6_Fissure1", + "Body_Bark6_Fissure2", + "Body_Bark6_Fissure3", + "Body_Bark7", + "Body_Bark7_Fissure0", + "Body_Bark7_Fissure1", + "Body_Bark7_Fissure2", + "Body_Bark7_Fissure3", + "Body_Bark8", + "Body_Bark8_Fissure0", + "Body_Bark8_Fissure1", + "Body_Bark8_Fissure2", + "Body_Bark8_Fissure3", + "Body_Blossom_Petal0", + "Body_Blossom_Petal1", + "Body_Blossom_Petal2", + "Body_Blossom_Petal3", + "Body_Blossom_Petal4", + "Body_Blossom_Pollen", + "Body_MossHeart", + "Body_ShoulderLeaf0", + "Body_ShoulderLeaf0_Midrib", + "Body_ShoulderLeaf0_Vein0_1", + "Body_ShoulderLeaf0_Vein0__1", + "Body_ShoulderLeaf0_Vein1_1", + "Body_ShoulderLeaf0_Vein1__1", + "Body_ShoulderLeaf0_Vein2_1", + "Body_ShoulderLeaf0_Vein2__1", + "Body_ShoulderLeaf1", + "Body_ShoulderLeaf1_Midrib", + "Body_ShoulderLeaf1_Vein0_1", + "Body_ShoulderLeaf1_Vein0__1", + "Body_ShoulderLeaf1_Vein1_1", + "Body_ShoulderLeaf1_Vein1__1", + "Body_ShoulderLeaf1_Vein2_1", + "Body_ShoulderLeaf1_Vein2__1", + "Body_ShoulderLeaf2", + "Body_ShoulderLeaf2_Midrib", + "Body_ShoulderLeaf2_Vein0_1", + "Body_ShoulderLeaf2_Vein0__1", + "Body_ShoulderLeaf2_Vein1_1", + "Body_ShoulderLeaf2_Vein1__1", + "Body_ShoulderLeaf2_Vein2_1", + "Body_ShoulderLeaf2_Vein2__1", + "Body_ShoulderLeaf3", + "Body_ShoulderLeaf3_Midrib", + "Body_ShoulderLeaf3_Vein0_1", + "Body_ShoulderLeaf3_Vein0__1", + "Body_ShoulderLeaf3_Vein1_1", + "Body_ShoulderLeaf3_Vein1__1", + "Body_ShoulderLeaf3_Vein2_1", + "Body_ShoulderLeaf3_Vein2__1", + "Body_Thorn0", + "Body_Thorn1", + "Body_Thorn2", + "Body_Thorn3", + "Body_Thorn4", + "Body_Thorn5", + "Body_Thorn6", + "Body_Thorn7", + "Body_Thorn8", + "Body_WovenBark0", + "Body_WovenBark0_Grain0", + "Body_WovenBark0_Grain1", + "Body_WovenBark1", + "Body_WovenBark1_Grain0", + "Body_WovenBark1_Grain1", + "Body_WovenBark2", + "Body_WovenBark2_Grain0", + "Body_WovenBark2_Grain1", + "Body_WovenBark3", + "Body_WovenBark3_Grain0", + "Body_WovenBark3_Grain1", + "Body_WovenBark4", + "Body_WovenBark4_Grain0", + "Body_WovenBark4_Grain1", + "Body_WovenBark5", + "Body_WovenBark5_Grain0", + "Body_WovenBark5_Grain1", + "Head_Eye1", + "Head_EyeShadow", + "Head_Eye_1", + "Head_Sprout1", + "Head_Sprout1_Midrib", + "Head_Sprout1_Vein0_1", + "Head_Sprout1_Vein0__1", + "Head_Sprout1_Vein1_1", + "Head_Sprout1_Vein1__1", + "Head_Sprout1_Vein2_1", + "Head_Sprout1_Vein2__1", + "Head_Sprout_1", + "Head_Sprout_1_Midrib", + "Head_Sprout_1_Vein0_1", + "Head_Sprout_1_Vein0__1", + "Head_Sprout_1_Vein1_1", + "Head_Sprout_1_Vein1__1", + "Head_Sprout_1_Vein2_1", + "Head_Sprout_1_Vein2__1", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w02", + "file": "unit_w02.glb", + "errors": [], + "warnings": [], + "triangles": 78020, + "mesh_parts": 237, + "primitives": 237, + "vertices": 39941, + "closed_meshes": 237, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_JawDark", + "Head_JawFlower_Petal0", + "Head_JawFlower_Petal1", + "Head_JawFlower_Petal2", + "Head_JawFlower_Petal3", + "Head_JawFlower_Petal4", + "Head_JawFlower_Pollen", + "Head_JawLeaf0", + "Head_JawLeaf0_Midrib", + "Head_JawLeaf0_Vein0_1", + "Head_JawLeaf0_Vein0__1", + "Head_JawLeaf0_Vein1_1", + "Head_JawLeaf0_Vein1__1", + "Head_JawLeaf0_Vein2_1", + "Head_JawLeaf0_Vein2__1", + "Head_JawLeaf1", + "Head_JawLeaf1_Midrib", + "Head_JawLeaf1_Vein0_1", + "Head_JawLeaf1_Vein0__1", + "Head_JawLeaf1_Vein1_1", + "Head_JawLeaf1_Vein1__1", + "Head_JawLeaf1_Vein2_1", + "Head_JawLeaf1_Vein2__1", + "Head_JawLeaf2", + "Head_JawLeaf2_Midrib", + "Head_JawLeaf2_Vein0_1", + "Head_JawLeaf2_Vein0__1", + "Head_JawLeaf2_Vein1_1", + "Head_JawLeaf2_Vein1__1", + "Head_JawLeaf2_Vein2_1", + "Head_JawLeaf2_Vein2__1", + "Head_JawLeaf3", + "Head_JawLeaf3_Midrib", + "Head_JawLeaf3_Vein0_1", + "Head_JawLeaf3_Vein0__1", + "Head_JawLeaf3_Vein1_1", + "Head_JawLeaf3_Vein1__1", + "Head_JawLeaf3_Vein2_1", + "Head_JawLeaf3_Vein2__1", + "Head_JawLeaf4", + "Head_JawLeaf4_Midrib", + "Head_JawLeaf4_Vein0_1", + "Head_JawLeaf4_Vein0__1", + "Head_JawLeaf4_Vein1_1", + "Head_JawLeaf4_Vein1__1", + "Head_JawLeaf4_Vein2_1", + "Head_JawLeaf4_Vein2__1", + "Head_JawLeaf5", + "Head_JawLeaf5_Midrib", + "Head_JawLeaf5_Vein0_1", + "Head_JawLeaf5_Vein0__1", + "Head_JawLeaf5_Vein1_1", + "Head_JawLeaf5_Vein1__1", + "Head_JawLeaf5_Vein2_1", + "Head_JawLeaf5_Vein2__1", + "Head_Lower_Fang0", + "Head_Lower_Fang1", + "Head_Lower_Fang2", + "Head_Lower_Fang3", + "Head_Lower_Fang4", + "Head_Lower_Fang5", + "Head_Lower_Fang6", + "Head_Lower_Fang7", + "Head_Lower_Fang8", + "Head_Lower_Jaw", + "Head_Lower_Lip0", + "Head_Lower_Lip1", + "Head_Lower_Lip2", + "Head_Upper_Fang0", + "Head_Upper_Fang1", + "Head_Upper_Fang2", + "Head_Upper_Fang3", + "Head_Upper_Fang4", + "Head_Upper_Fang5", + "Head_Upper_Fang6", + "Head_Upper_Fang7", + "Head_Upper_Fang8", + "Head_Upper_Jaw", + "Head_Upper_Lip0", + "Head_Upper_Lip1", + "Head_Upper_Lip2", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w03", + "file": "unit_w03.glb", + "errors": [], + "warnings": [], + "triangles": 84786, + "mesh_parts": 380, + "primitives": 380, + "vertices": 44591, + "closed_meshes": 380, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_Cork0_0", + "Body_Cork0_0_Fissure0", + "Body_Cork0_0_Fissure1", + "Body_Cork0_0_Fissure2", + "Body_Cork0_0_Fissure3", + "Body_Cork0_1", + "Body_Cork0_1_Fissure0", + "Body_Cork0_1_Fissure1", + "Body_Cork0_1_Fissure2", + "Body_Cork0_1_Fissure3", + "Body_Cork0_2", + "Body_Cork0_2_Fissure0", + "Body_Cork0_2_Fissure1", + "Body_Cork0_2_Fissure2", + "Body_Cork0_2_Fissure3", + "Body_Cork0_3", + "Body_Cork0_3_Fissure0", + "Body_Cork0_3_Fissure1", + "Body_Cork0_3_Fissure2", + "Body_Cork0_3_Fissure3", + "Body_Cork0_4", + "Body_Cork0_4_Fissure0", + "Body_Cork0_4_Fissure1", + "Body_Cork0_4_Fissure2", + "Body_Cork0_4_Fissure3", + "Body_Cork0_5", + "Body_Cork0_5_Fissure0", + "Body_Cork0_5_Fissure1", + "Body_Cork0_5_Fissure2", + "Body_Cork0_5_Fissure3", + "Body_Cork0_6", + "Body_Cork0_6_Fissure0", + "Body_Cork0_6_Fissure1", + "Body_Cork0_6_Fissure2", + "Body_Cork0_6_Fissure3", + "Body_Cork1_0", + "Body_Cork1_0_Fissure0", + "Body_Cork1_0_Fissure1", + "Body_Cork1_0_Fissure2", + "Body_Cork1_0_Fissure3", + "Body_Cork1_1", + "Body_Cork1_1_Fissure0", + "Body_Cork1_1_Fissure1", + "Body_Cork1_1_Fissure2", + "Body_Cork1_1_Fissure3", + "Body_Cork1_2", + "Body_Cork1_2_Fissure0", + "Body_Cork1_2_Fissure1", + "Body_Cork1_2_Fissure2", + "Body_Cork1_2_Fissure3", + "Body_Cork1_3", + "Body_Cork1_3_Fissure0", + "Body_Cork1_3_Fissure1", + "Body_Cork1_3_Fissure2", + "Body_Cork1_3_Fissure3", + "Body_Cork1_4", + "Body_Cork1_4_Fissure0", + "Body_Cork1_4_Fissure1", + "Body_Cork1_4_Fissure2", + "Body_Cork1_4_Fissure3", + "Body_Cork1_5", + "Body_Cork1_5_Fissure0", + "Body_Cork1_5_Fissure1", + "Body_Cork1_5_Fissure2", + "Body_Cork1_5_Fissure3", + "Body_Cork1_6", + "Body_Cork1_6_Fissure0", + "Body_Cork1_6_Fissure1", + "Body_Cork1_6_Fissure2", + "Body_Cork1_6_Fissure3", + "Body_Cork2_0", + "Body_Cork2_0_Fissure0", + "Body_Cork2_0_Fissure1", + "Body_Cork2_0_Fissure2", + "Body_Cork2_0_Fissure3", + "Body_Cork2_1", + "Body_Cork2_1_Fissure0", + "Body_Cork2_1_Fissure1", + "Body_Cork2_1_Fissure2", + "Body_Cork2_1_Fissure3", + "Body_Cork2_2", + "Body_Cork2_2_Fissure0", + "Body_Cork2_2_Fissure1", + "Body_Cork2_2_Fissure2", + "Body_Cork2_2_Fissure3", + "Body_Cork2_3", + "Body_Cork2_3_Fissure0", + "Body_Cork2_3_Fissure1", + "Body_Cork2_3_Fissure2", + "Body_Cork2_3_Fissure3", + "Body_Cork2_4", + "Body_Cork2_4_Fissure0", + "Body_Cork2_4_Fissure1", + "Body_Cork2_4_Fissure2", + "Body_Cork2_4_Fissure3", + "Body_Cork2_5", + "Body_Cork2_5_Fissure0", + "Body_Cork2_5_Fissure1", + "Body_Cork2_5_Fissure2", + "Body_Cork2_5_Fissure3", + "Body_Cork2_6", + "Body_Cork2_6_Fissure0", + "Body_Cork2_6_Fissure1", + "Body_Cork2_6_Fissure2", + "Body_Cork2_6_Fissure3", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen", + "Body_InnerMoss", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w04", + "file": "unit_w04.glb", + "errors": [], + "warnings": [], + "triangles": 134530, + "mesh_parts": 539, + "primitives": 539, + "vertices": 121797, + "closed_meshes": 539, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen", + "Body_InnerMoss", + "Body_Log0_Bark", + "Body_Log0_Cut", + "Body_Log0_Growth0", + "Body_Log0_Growth1", + "Body_Log0_Growth2", + "Body_Log0_Growth3", + "Body_Log0_Growth4", + "Body_Log0_Growth5", + "Body_Log0_RoughEdge0", + "Body_Log0_RoughEdge1", + "Body_Log0_RoughEdge10", + "Body_Log0_RoughEdge11", + "Body_Log0_RoughEdge12", + "Body_Log0_RoughEdge2", + "Body_Log0_RoughEdge3", + "Body_Log0_RoughEdge4", + "Body_Log0_RoughEdge5", + "Body_Log0_RoughEdge6", + "Body_Log0_RoughEdge7", + "Body_Log0_RoughEdge8", + "Body_Log0_RoughEdge9", + "Body_Log0_Split0", + "Body_Log0_Split1", + "Body_Log0_Split2", + "Body_Log1_Bark", + "Body_Log1_Cut", + "Body_Log1_Growth0", + "Body_Log1_Growth1", + "Body_Log1_Growth2", + "Body_Log1_Growth3", + "Body_Log1_Growth4", + "Body_Log1_Growth5", + "Body_Log1_RoughEdge0", + "Body_Log1_RoughEdge1", + "Body_Log1_RoughEdge10", + "Body_Log1_RoughEdge11", + "Body_Log1_RoughEdge12", + "Body_Log1_RoughEdge2", + "Body_Log1_RoughEdge3", + "Body_Log1_RoughEdge4", + "Body_Log1_RoughEdge5", + "Body_Log1_RoughEdge6", + "Body_Log1_RoughEdge7", + "Body_Log1_RoughEdge8", + "Body_Log1_RoughEdge9", + "Body_Log1_Split0", + "Body_Log1_Split1", + "Body_Log1_Split2", + "Body_Log2_Bark", + "Body_Log2_Cut", + "Body_Log2_Growth0", + "Body_Log2_Growth1", + "Body_Log2_Growth2", + "Body_Log2_Growth3", + "Body_Log2_Growth4", + "Body_Log2_Growth5", + "Body_Log2_RoughEdge0", + "Body_Log2_RoughEdge1", + "Body_Log2_RoughEdge10", + "Body_Log2_RoughEdge11", + "Body_Log2_RoughEdge12", + "Body_Log2_RoughEdge2", + "Body_Log2_RoughEdge3", + "Body_Log2_RoughEdge4", + "Body_Log2_RoughEdge5", + "Body_Log2_RoughEdge6", + "Body_Log2_RoughEdge7", + "Body_Log2_RoughEdge8", + "Body_Log2_RoughEdge9", + "Body_Log2_Split0", + "Body_Log2_Split1", + "Body_Log2_Split2", + "Body_Log3_Bark", + "Body_Log3_Cut", + "Body_Log3_Growth0", + "Body_Log3_Growth1", + "Body_Log3_Growth2", + "Body_Log3_Growth3", + "Body_Log3_Growth4", + "Body_Log3_Growth5", + "Body_Log3_RoughEdge0", + "Body_Log3_RoughEdge1", + "Body_Log3_RoughEdge10", + "Body_Log3_RoughEdge11", + "Body_Log3_RoughEdge12", + "Body_Log3_RoughEdge2", + "Body_Log3_RoughEdge3", + "Body_Log3_RoughEdge4", + "Body_Log3_RoughEdge5", + "Body_Log3_RoughEdge6", + "Body_Log3_RoughEdge7", + "Body_Log3_RoughEdge8", + "Body_Log3_RoughEdge9", + "Body_Log3_Split0", + "Body_Log3_Split1", + "Body_Log3_Split2", + "Body_Log4_Bark", + "Body_Log4_Cut", + "Body_Log4_Growth0", + "Body_Log4_Growth1", + "Body_Log4_Growth2", + "Body_Log4_Growth3", + "Body_Log4_Growth4", + "Body_Log4_Growth5", + "Body_Log4_RoughEdge0", + "Body_Log4_RoughEdge1", + "Body_Log4_RoughEdge10", + "Body_Log4_RoughEdge11", + "Body_Log4_RoughEdge12", + "Body_Log4_RoughEdge2", + "Body_Log4_RoughEdge3", + "Body_Log4_RoughEdge4", + "Body_Log4_RoughEdge5", + "Body_Log4_RoughEdge6", + "Body_Log4_RoughEdge7", + "Body_Log4_RoughEdge8", + "Body_Log4_RoughEdge9", + "Body_Log4_Split0", + "Body_Log4_Split1", + "Body_Log4_Split2", + "Body_Log5_Bark", + "Body_Log5_Cut", + "Body_Log5_Growth0", + "Body_Log5_Growth1", + "Body_Log5_Growth2", + "Body_Log5_Growth3", + "Body_Log5_Growth4", + "Body_Log5_Growth5", + "Body_Log5_RoughEdge0", + "Body_Log5_RoughEdge1", + "Body_Log5_RoughEdge10", + "Body_Log5_RoughEdge11", + "Body_Log5_RoughEdge12", + "Body_Log5_RoughEdge2", + "Body_Log5_RoughEdge3", + "Body_Log5_RoughEdge4", + "Body_Log5_RoughEdge5", + "Body_Log5_RoughEdge6", + "Body_Log5_RoughEdge7", + "Body_Log5_RoughEdge8", + "Body_Log5_RoughEdge9", + "Body_Log5_Split0", + "Body_Log5_Split1", + "Body_Log5_Split2", + "Body_OverlappingBark0_0", + "Body_OverlappingBark0_0_Fissure0", + "Body_OverlappingBark0_0_Fissure1", + "Body_OverlappingBark0_0_Fissure2", + "Body_OverlappingBark0_0_Fissure3", + "Body_OverlappingBark0_1", + "Body_OverlappingBark0_1_Fissure0", + "Body_OverlappingBark0_1_Fissure1", + "Body_OverlappingBark0_1_Fissure2", + "Body_OverlappingBark0_1_Fissure3", + "Body_OverlappingBark0_2", + "Body_OverlappingBark0_2_Fissure0", + "Body_OverlappingBark0_2_Fissure1", + "Body_OverlappingBark0_2_Fissure2", + "Body_OverlappingBark0_2_Fissure3", + "Body_OverlappingBark0_3", + "Body_OverlappingBark0_3_Fissure0", + "Body_OverlappingBark0_3_Fissure1", + "Body_OverlappingBark0_3_Fissure2", + "Body_OverlappingBark0_3_Fissure3", + "Body_OverlappingBark0_4", + "Body_OverlappingBark0_4_Fissure0", + "Body_OverlappingBark0_4_Fissure1", + "Body_OverlappingBark0_4_Fissure2", + "Body_OverlappingBark0_4_Fissure3", + "Body_OverlappingBark0_5", + "Body_OverlappingBark0_5_Fissure0", + "Body_OverlappingBark0_5_Fissure1", + "Body_OverlappingBark0_5_Fissure2", + "Body_OverlappingBark0_5_Fissure3", + "Body_OverlappingBark0_6", + "Body_OverlappingBark0_6_Fissure0", + "Body_OverlappingBark0_6_Fissure1", + "Body_OverlappingBark0_6_Fissure2", + "Body_OverlappingBark0_6_Fissure3", + "Body_OverlappingBark0_7", + "Body_OverlappingBark0_7_Fissure0", + "Body_OverlappingBark0_7_Fissure1", + "Body_OverlappingBark0_7_Fissure2", + "Body_OverlappingBark0_7_Fissure3", + "Body_OverlappingBark1_0", + "Body_OverlappingBark1_0_Fissure0", + "Body_OverlappingBark1_0_Fissure1", + "Body_OverlappingBark1_0_Fissure2", + "Body_OverlappingBark1_0_Fissure3", + "Body_OverlappingBark1_1", + "Body_OverlappingBark1_1_Fissure0", + "Body_OverlappingBark1_1_Fissure1", + "Body_OverlappingBark1_1_Fissure2", + "Body_OverlappingBark1_1_Fissure3", + "Body_OverlappingBark1_2", + "Body_OverlappingBark1_2_Fissure0", + "Body_OverlappingBark1_2_Fissure1", + "Body_OverlappingBark1_2_Fissure2", + "Body_OverlappingBark1_2_Fissure3", + "Body_OverlappingBark1_3", + "Body_OverlappingBark1_3_Fissure0", + "Body_OverlappingBark1_3_Fissure1", + "Body_OverlappingBark1_3_Fissure2", + "Body_OverlappingBark1_3_Fissure3", + "Body_OverlappingBark1_4", + "Body_OverlappingBark1_4_Fissure0", + "Body_OverlappingBark1_4_Fissure1", + "Body_OverlappingBark1_4_Fissure2", + "Body_OverlappingBark1_4_Fissure3", + "Body_OverlappingBark1_5", + "Body_OverlappingBark1_5_Fissure0", + "Body_OverlappingBark1_5_Fissure1", + "Body_OverlappingBark1_5_Fissure2", + "Body_OverlappingBark1_5_Fissure3", + "Body_OverlappingBark1_6", + "Body_OverlappingBark1_6_Fissure0", + "Body_OverlappingBark1_6_Fissure1", + "Body_OverlappingBark1_6_Fissure2", + "Body_OverlappingBark1_6_Fissure3", + "Body_OverlappingBark1_7", + "Body_OverlappingBark1_7_Fissure0", + "Body_OverlappingBark1_7_Fissure1", + "Body_OverlappingBark1_7_Fissure2", + "Body_OverlappingBark1_7_Fissure3", + "Body_OverlappingBark2_0", + "Body_OverlappingBark2_0_Fissure0", + "Body_OverlappingBark2_0_Fissure1", + "Body_OverlappingBark2_0_Fissure2", + "Body_OverlappingBark2_0_Fissure3", + "Body_OverlappingBark2_1", + "Body_OverlappingBark2_1_Fissure0", + "Body_OverlappingBark2_1_Fissure1", + "Body_OverlappingBark2_1_Fissure2", + "Body_OverlappingBark2_1_Fissure3", + "Body_OverlappingBark2_2", + "Body_OverlappingBark2_2_Fissure0", + "Body_OverlappingBark2_2_Fissure1", + "Body_OverlappingBark2_2_Fissure2", + "Body_OverlappingBark2_2_Fissure3", + "Body_OverlappingBark2_3", + "Body_OverlappingBark2_3_Fissure0", + "Body_OverlappingBark2_3_Fissure1", + "Body_OverlappingBark2_3_Fissure2", + "Body_OverlappingBark2_3_Fissure3", + "Body_OverlappingBark2_4", + "Body_OverlappingBark2_4_Fissure0", + "Body_OverlappingBark2_4_Fissure1", + "Body_OverlappingBark2_4_Fissure2", + "Body_OverlappingBark2_4_Fissure3", + "Body_OverlappingBark2_5", + "Body_OverlappingBark2_5_Fissure0", + "Body_OverlappingBark2_5_Fissure1", + "Body_OverlappingBark2_5_Fissure2", + "Body_OverlappingBark2_5_Fissure3", + "Body_OverlappingBark2_6", + "Body_OverlappingBark2_6_Fissure0", + "Body_OverlappingBark2_6_Fissure1", + "Body_OverlappingBark2_6_Fissure2", + "Body_OverlappingBark2_6_Fissure3", + "Body_OverlappingBark2_7", + "Body_OverlappingBark2_7_Fissure0", + "Body_OverlappingBark2_7_Fissure1", + "Body_OverlappingBark2_7_Fissure2", + "Body_OverlappingBark2_7_Fissure3", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w05", + "file": "unit_w05.glb", + "errors": [], + "warnings": [], + "triangles": 50536, + "mesh_parts": 204, + "primitives": 204, + "vertices": 26202, + "closed_meshes": 204, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein2_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale4_Vein2__1", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Launcher_Rim", + "Head_Launcher_Shell", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w06", + "file": "unit_w06.glb", + "errors": [], + "warnings": [], + "triangles": 62588, + "mesh_parts": 296, + "primitives": 296, + "vertices": 32464, + "closed_meshes": 296, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein2_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale1", + "Head_LauncherScale10", + "Head_LauncherScale10_Midrib", + "Head_LauncherScale10_Vein0_1", + "Head_LauncherScale10_Vein0__1", + "Head_LauncherScale10_Vein1_1", + "Head_LauncherScale10_Vein1__1", + "Head_LauncherScale10_Vein2_1", + "Head_LauncherScale10_Vein2__1", + "Head_LauncherScale11", + "Head_LauncherScale11_Midrib", + "Head_LauncherScale11_Vein0_1", + "Head_LauncherScale11_Vein0__1", + "Head_LauncherScale11_Vein1_1", + "Head_LauncherScale11_Vein1__1", + "Head_LauncherScale11_Vein2_1", + "Head_LauncherScale11_Vein2__1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale5", + "Head_LauncherScale5_Midrib", + "Head_LauncherScale5_Vein0_1", + "Head_LauncherScale5_Vein0__1", + "Head_LauncherScale5_Vein1_1", + "Head_LauncherScale5_Vein1__1", + "Head_LauncherScale5_Vein2_1", + "Head_LauncherScale5_Vein2__1", + "Head_LauncherScale6", + "Head_LauncherScale6_Midrib", + "Head_LauncherScale6_Vein0_1", + "Head_LauncherScale6_Vein0__1", + "Head_LauncherScale6_Vein1_1", + "Head_LauncherScale6_Vein1__1", + "Head_LauncherScale6_Vein2_1", + "Head_LauncherScale6_Vein2__1", + "Head_LauncherScale7", + "Head_LauncherScale7_Midrib", + "Head_LauncherScale7_Vein0_1", + "Head_LauncherScale7_Vein0__1", + "Head_LauncherScale7_Vein1_1", + "Head_LauncherScale7_Vein1__1", + "Head_LauncherScale7_Vein2_1", + "Head_LauncherScale7_Vein2__1", + "Head_LauncherScale8", + "Head_LauncherScale8_Midrib", + "Head_LauncherScale8_Vein0_1", + "Head_LauncherScale8_Vein0__1", + "Head_LauncherScale8_Vein1_1", + "Head_LauncherScale8_Vein1__1", + "Head_LauncherScale8_Vein2_1", + "Head_LauncherScale8_Vein2__1", + "Head_LauncherScale9", + "Head_LauncherScale9_Midrib", + "Head_LauncherScale9_Vein0_1", + "Head_LauncherScale9_Vein0__1", + "Head_LauncherScale9_Vein1_1", + "Head_LauncherScale9_Vein1__1", + "Head_LauncherScale9_Vein2_1", + "Head_LauncherScale9_Vein2__1", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Launcher_Rim", + "Head_Launcher_Shell", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w07", + "file": "unit_w07.glb", + "errors": [], + "warnings": [], + "triangles": 69164, + "mesh_parts": 366, + "primitives": 366, + "vertices": 35748, + "closed_meshes": 366, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Shell", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Shell", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein2_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Rib0", + "Head_Cup0_Rib1", + "Head_Cup0_Rib10", + "Head_Cup0_Rib11", + "Head_Cup0_Rib2", + "Head_Cup0_Rib3", + "Head_Cup0_Rib4", + "Head_Cup0_Rib5", + "Head_Cup0_Rib6", + "Head_Cup0_Rib7", + "Head_Cup0_Rib8", + "Head_Cup0_Rib9", + "Head_Cup0_Rim", + "Head_Cup0_Shell", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4" + ] + }, + { + "id": "w08", + "file": "unit_w08.glb", + "errors": [], + "warnings": [], + "triangles": 103748, + "mesh_parts": 700, + "primitives": 700, + "vertices": 54201, + "closed_meshes": 700, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Body_FungalTrunk1", + "Body_FungalTrunk1_Grain0", + "Body_FungalTrunk1_Grain1", + "Body_FungalTrunk1_Grain2", + "Body_FungalTrunk1_Grain3", + "Body_FungalTrunk2", + "Body_FungalTrunk2_Grain0", + "Body_FungalTrunk2_Grain1", + "Body_FungalTrunk2_Grain2", + "Body_FungalTrunk2_Grain3", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Shell", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Shell", + "Body_SmallCup2_Fringe0", + "Body_SmallCup2_Fringe0_Midrib", + "Body_SmallCup2_Fringe0_Vein0_1", + "Body_SmallCup2_Fringe0_Vein0__1", + "Body_SmallCup2_Fringe0_Vein1_1", + "Body_SmallCup2_Fringe0_Vein1__1", + "Body_SmallCup2_Fringe0_Vein2_1", + "Body_SmallCup2_Fringe0_Vein2__1", + "Body_SmallCup2_Fringe1", + "Body_SmallCup2_Fringe1_Midrib", + "Body_SmallCup2_Fringe1_Vein0_1", + "Body_SmallCup2_Fringe1_Vein0__1", + "Body_SmallCup2_Fringe1_Vein1_1", + "Body_SmallCup2_Fringe1_Vein1__1", + "Body_SmallCup2_Fringe1_Vein2_1", + "Body_SmallCup2_Fringe1_Vein2__1", + "Body_SmallCup2_Fringe2", + "Body_SmallCup2_Fringe2_Midrib", + "Body_SmallCup2_Fringe2_Vein0_1", + "Body_SmallCup2_Fringe2_Vein0__1", + "Body_SmallCup2_Fringe2_Vein1_1", + "Body_SmallCup2_Fringe2_Vein1__1", + "Body_SmallCup2_Fringe2_Vein2_1", + "Body_SmallCup2_Fringe2_Vein2__1", + "Body_SmallCup2_Fringe3", + "Body_SmallCup2_Fringe3_Midrib", + "Body_SmallCup2_Fringe3_Vein0_1", + "Body_SmallCup2_Fringe3_Vein0__1", + "Body_SmallCup2_Fringe3_Vein1_1", + "Body_SmallCup2_Fringe3_Vein1__1", + "Body_SmallCup2_Fringe3_Vein2_1", + "Body_SmallCup2_Fringe3_Vein2__1", + "Body_SmallCup2_Fringe4", + "Body_SmallCup2_Fringe4_Midrib", + "Body_SmallCup2_Fringe4_Vein0_1", + "Body_SmallCup2_Fringe4_Vein0__1", + "Body_SmallCup2_Fringe4_Vein1_1", + "Body_SmallCup2_Fringe4_Vein1__1", + "Body_SmallCup2_Fringe4_Vein2_1", + "Body_SmallCup2_Fringe4_Vein2__1", + "Body_SmallCup2_Rib0", + "Body_SmallCup2_Rib1", + "Body_SmallCup2_Rib2", + "Body_SmallCup2_Rib3", + "Body_SmallCup2_Rib4", + "Body_SmallCup2_Rim", + "Body_SmallCup2_Shell", + "Body_SmallCup3_Fringe0", + "Body_SmallCup3_Fringe0_Midrib", + "Body_SmallCup3_Fringe0_Vein0_1", + "Body_SmallCup3_Fringe0_Vein0__1", + "Body_SmallCup3_Fringe0_Vein1_1", + "Body_SmallCup3_Fringe0_Vein1__1", + "Body_SmallCup3_Fringe0_Vein2_1", + "Body_SmallCup3_Fringe0_Vein2__1", + "Body_SmallCup3_Fringe1", + "Body_SmallCup3_Fringe1_Midrib", + "Body_SmallCup3_Fringe1_Vein0_1", + "Body_SmallCup3_Fringe1_Vein0__1", + "Body_SmallCup3_Fringe1_Vein1_1", + "Body_SmallCup3_Fringe1_Vein1__1", + "Body_SmallCup3_Fringe1_Vein2_1", + "Body_SmallCup3_Fringe1_Vein2__1", + "Body_SmallCup3_Fringe2", + "Body_SmallCup3_Fringe2_Midrib", + "Body_SmallCup3_Fringe2_Vein0_1", + "Body_SmallCup3_Fringe2_Vein0__1", + "Body_SmallCup3_Fringe2_Vein1_1", + "Body_SmallCup3_Fringe2_Vein1__1", + "Body_SmallCup3_Fringe2_Vein2_1", + "Body_SmallCup3_Fringe2_Vein2__1", + "Body_SmallCup3_Fringe3", + "Body_SmallCup3_Fringe3_Midrib", + "Body_SmallCup3_Fringe3_Vein0_1", + "Body_SmallCup3_Fringe3_Vein0__1", + "Body_SmallCup3_Fringe3_Vein1_1", + "Body_SmallCup3_Fringe3_Vein1__1", + "Body_SmallCup3_Fringe3_Vein2_1", + "Body_SmallCup3_Fringe3_Vein2__1", + "Body_SmallCup3_Fringe4", + "Body_SmallCup3_Fringe4_Midrib", + "Body_SmallCup3_Fringe4_Vein0_1", + "Body_SmallCup3_Fringe4_Vein0__1", + "Body_SmallCup3_Fringe4_Vein1_1", + "Body_SmallCup3_Fringe4_Vein1__1", + "Body_SmallCup3_Fringe4_Vein2_1", + "Body_SmallCup3_Fringe4_Vein2__1", + "Body_SmallCup3_Rib0", + "Body_SmallCup3_Rib1", + "Body_SmallCup3_Rib2", + "Body_SmallCup3_Rib3", + "Body_SmallCup3_Rib4", + "Body_SmallCup3_Rim", + "Body_SmallCup3_Shell", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein2_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Rib0", + "Head_Cup0_Rib1", + "Head_Cup0_Rib10", + "Head_Cup0_Rib11", + "Head_Cup0_Rib2", + "Head_Cup0_Rib3", + "Head_Cup0_Rib4", + "Head_Cup0_Rib5", + "Head_Cup0_Rib6", + "Head_Cup0_Rib7", + "Head_Cup0_Rib8", + "Head_Cup0_Rib9", + "Head_Cup0_Rim", + "Head_Cup0_Shell", + "Head_Cup1_Fringe0", + "Head_Cup1_Fringe0_Midrib", + "Head_Cup1_Fringe0_Vein0_1", + "Head_Cup1_Fringe0_Vein0__1", + "Head_Cup1_Fringe0_Vein1_1", + "Head_Cup1_Fringe0_Vein1__1", + "Head_Cup1_Fringe0_Vein2_1", + "Head_Cup1_Fringe0_Vein2__1", + "Head_Cup1_Fringe1", + "Head_Cup1_Fringe10", + "Head_Cup1_Fringe10_Midrib", + "Head_Cup1_Fringe10_Vein0_1", + "Head_Cup1_Fringe10_Vein0__1", + "Head_Cup1_Fringe10_Vein1_1", + "Head_Cup1_Fringe10_Vein1__1", + "Head_Cup1_Fringe10_Vein2_1", + "Head_Cup1_Fringe10_Vein2__1", + "Head_Cup1_Fringe11", + "Head_Cup1_Fringe11_Midrib", + "Head_Cup1_Fringe11_Vein0_1", + "Head_Cup1_Fringe11_Vein0__1", + "Head_Cup1_Fringe11_Vein1_1", + "Head_Cup1_Fringe11_Vein1__1", + "Head_Cup1_Fringe11_Vein2_1", + "Head_Cup1_Fringe11_Vein2__1", + "Head_Cup1_Fringe1_Midrib", + "Head_Cup1_Fringe1_Vein0_1", + "Head_Cup1_Fringe1_Vein0__1", + "Head_Cup1_Fringe1_Vein1_1", + "Head_Cup1_Fringe1_Vein1__1", + "Head_Cup1_Fringe1_Vein2_1", + "Head_Cup1_Fringe1_Vein2__1", + "Head_Cup1_Fringe2", + "Head_Cup1_Fringe2_Midrib", + "Head_Cup1_Fringe2_Vein0_1", + "Head_Cup1_Fringe2_Vein0__1", + "Head_Cup1_Fringe2_Vein1_1", + "Head_Cup1_Fringe2_Vein1__1", + "Head_Cup1_Fringe2_Vein2_1", + "Head_Cup1_Fringe2_Vein2__1", + "Head_Cup1_Fringe3", + "Head_Cup1_Fringe3_Midrib", + "Head_Cup1_Fringe3_Vein0_1", + "Head_Cup1_Fringe3_Vein0__1", + "Head_Cup1_Fringe3_Vein1_1", + "Head_Cup1_Fringe3_Vein1__1", + "Head_Cup1_Fringe3_Vein2_1", + "Head_Cup1_Fringe3_Vein2__1", + "Head_Cup1_Fringe4", + "Head_Cup1_Fringe4_Midrib", + "Head_Cup1_Fringe4_Vein0_1", + "Head_Cup1_Fringe4_Vein0__1", + "Head_Cup1_Fringe4_Vein1_1", + "Head_Cup1_Fringe4_Vein1__1", + "Head_Cup1_Fringe4_Vein2_1", + "Head_Cup1_Fringe4_Vein2__1", + "Head_Cup1_Fringe5", + "Head_Cup1_Fringe5_Midrib", + "Head_Cup1_Fringe5_Vein0_1", + "Head_Cup1_Fringe5_Vein0__1", + "Head_Cup1_Fringe5_Vein1_1", + "Head_Cup1_Fringe5_Vein1__1", + "Head_Cup1_Fringe5_Vein2_1", + "Head_Cup1_Fringe5_Vein2__1", + "Head_Cup1_Fringe6", + "Head_Cup1_Fringe6_Midrib", + "Head_Cup1_Fringe6_Vein0_1", + "Head_Cup1_Fringe6_Vein0__1", + "Head_Cup1_Fringe6_Vein1_1", + "Head_Cup1_Fringe6_Vein1__1", + "Head_Cup1_Fringe6_Vein2_1", + "Head_Cup1_Fringe6_Vein2__1", + "Head_Cup1_Fringe7", + "Head_Cup1_Fringe7_Midrib", + "Head_Cup1_Fringe7_Vein0_1", + "Head_Cup1_Fringe7_Vein0__1", + "Head_Cup1_Fringe7_Vein1_1", + "Head_Cup1_Fringe7_Vein1__1", + "Head_Cup1_Fringe7_Vein2_1", + "Head_Cup1_Fringe7_Vein2__1", + "Head_Cup1_Fringe8", + "Head_Cup1_Fringe8_Midrib", + "Head_Cup1_Fringe8_Vein0_1", + "Head_Cup1_Fringe8_Vein0__1", + "Head_Cup1_Fringe8_Vein1_1", + "Head_Cup1_Fringe8_Vein1__1", + "Head_Cup1_Fringe8_Vein2_1", + "Head_Cup1_Fringe8_Vein2__1", + "Head_Cup1_Fringe9", + "Head_Cup1_Fringe9_Midrib", + "Head_Cup1_Fringe9_Vein0_1", + "Head_Cup1_Fringe9_Vein0__1", + "Head_Cup1_Fringe9_Vein1_1", + "Head_Cup1_Fringe9_Vein1__1", + "Head_Cup1_Fringe9_Vein2_1", + "Head_Cup1_Fringe9_Vein2__1", + "Head_Cup1_Rib0", + "Head_Cup1_Rib1", + "Head_Cup1_Rib10", + "Head_Cup1_Rib11", + "Head_Cup1_Rib2", + "Head_Cup1_Rib3", + "Head_Cup1_Rib4", + "Head_Cup1_Rib5", + "Head_Cup1_Rib6", + "Head_Cup1_Rib7", + "Head_Cup1_Rib8", + "Head_Cup1_Rib9", + "Head_Cup1_Rim", + "Head_Cup1_Shell", + "Head_Cup2_Fringe0", + "Head_Cup2_Fringe0_Midrib", + "Head_Cup2_Fringe0_Vein0_1", + "Head_Cup2_Fringe0_Vein0__1", + "Head_Cup2_Fringe0_Vein1_1", + "Head_Cup2_Fringe0_Vein1__1", + "Head_Cup2_Fringe0_Vein2_1", + "Head_Cup2_Fringe0_Vein2__1", + "Head_Cup2_Fringe1", + "Head_Cup2_Fringe10", + "Head_Cup2_Fringe10_Midrib", + "Head_Cup2_Fringe10_Vein0_1", + "Head_Cup2_Fringe10_Vein0__1", + "Head_Cup2_Fringe10_Vein1_1", + "Head_Cup2_Fringe10_Vein1__1", + "Head_Cup2_Fringe10_Vein2_1", + "Head_Cup2_Fringe10_Vein2__1", + "Head_Cup2_Fringe11", + "Head_Cup2_Fringe11_Midrib", + "Head_Cup2_Fringe11_Vein0_1", + "Head_Cup2_Fringe11_Vein0__1", + "Head_Cup2_Fringe11_Vein1_1", + "Head_Cup2_Fringe11_Vein1__1", + "Head_Cup2_Fringe11_Vein2_1", + "Head_Cup2_Fringe11_Vein2__1", + "Head_Cup2_Fringe1_Midrib", + "Head_Cup2_Fringe1_Vein0_1", + "Head_Cup2_Fringe1_Vein0__1", + "Head_Cup2_Fringe1_Vein1_1", + "Head_Cup2_Fringe1_Vein1__1", + "Head_Cup2_Fringe1_Vein2_1", + "Head_Cup2_Fringe1_Vein2__1", + "Head_Cup2_Fringe2", + "Head_Cup2_Fringe2_Midrib", + "Head_Cup2_Fringe2_Vein0_1", + "Head_Cup2_Fringe2_Vein0__1", + "Head_Cup2_Fringe2_Vein1_1", + "Head_Cup2_Fringe2_Vein1__1", + "Head_Cup2_Fringe2_Vein2_1", + "Head_Cup2_Fringe2_Vein2__1", + "Head_Cup2_Fringe3", + "Head_Cup2_Fringe3_Midrib", + "Head_Cup2_Fringe3_Vein0_1", + "Head_Cup2_Fringe3_Vein0__1", + "Head_Cup2_Fringe3_Vein1_1", + "Head_Cup2_Fringe3_Vein1__1", + "Head_Cup2_Fringe3_Vein2_1", + "Head_Cup2_Fringe3_Vein2__1", + "Head_Cup2_Fringe4", + "Head_Cup2_Fringe4_Midrib", + "Head_Cup2_Fringe4_Vein0_1", + "Head_Cup2_Fringe4_Vein0__1", + "Head_Cup2_Fringe4_Vein1_1", + "Head_Cup2_Fringe4_Vein1__1", + "Head_Cup2_Fringe4_Vein2_1", + "Head_Cup2_Fringe4_Vein2__1", + "Head_Cup2_Fringe5", + "Head_Cup2_Fringe5_Midrib", + "Head_Cup2_Fringe5_Vein0_1", + "Head_Cup2_Fringe5_Vein0__1", + "Head_Cup2_Fringe5_Vein1_1", + "Head_Cup2_Fringe5_Vein1__1", + "Head_Cup2_Fringe5_Vein2_1", + "Head_Cup2_Fringe5_Vein2__1", + "Head_Cup2_Fringe6", + "Head_Cup2_Fringe6_Midrib", + "Head_Cup2_Fringe6_Vein0_1", + "Head_Cup2_Fringe6_Vein0__1", + "Head_Cup2_Fringe6_Vein1_1", + "Head_Cup2_Fringe6_Vein1__1", + "Head_Cup2_Fringe6_Vein2_1", + "Head_Cup2_Fringe6_Vein2__1", + "Head_Cup2_Fringe7", + "Head_Cup2_Fringe7_Midrib", + "Head_Cup2_Fringe7_Vein0_1", + "Head_Cup2_Fringe7_Vein0__1", + "Head_Cup2_Fringe7_Vein1_1", + "Head_Cup2_Fringe7_Vein1__1", + "Head_Cup2_Fringe7_Vein2_1", + "Head_Cup2_Fringe7_Vein2__1", + "Head_Cup2_Fringe8", + "Head_Cup2_Fringe8_Midrib", + "Head_Cup2_Fringe8_Vein0_1", + "Head_Cup2_Fringe8_Vein0__1", + "Head_Cup2_Fringe8_Vein1_1", + "Head_Cup2_Fringe8_Vein1__1", + "Head_Cup2_Fringe8_Vein2_1", + "Head_Cup2_Fringe8_Vein2__1", + "Head_Cup2_Fringe9", + "Head_Cup2_Fringe9_Midrib", + "Head_Cup2_Fringe9_Vein0_1", + "Head_Cup2_Fringe9_Vein0__1", + "Head_Cup2_Fringe9_Vein1_1", + "Head_Cup2_Fringe9_Vein1__1", + "Head_Cup2_Fringe9_Vein2_1", + "Head_Cup2_Fringe9_Vein2__1", + "Head_Cup2_Rib0", + "Head_Cup2_Rib1", + "Head_Cup2_Rib10", + "Head_Cup2_Rib11", + "Head_Cup2_Rib2", + "Head_Cup2_Rib3", + "Head_Cup2_Rib4", + "Head_Cup2_Rib5", + "Head_Cup2_Rib6", + "Head_Cup2_Rib7", + "Head_Cup2_Rib8", + "Head_Cup2_Rib9", + "Head_Cup2_Rim", + "Head_Cup2_Shell", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Weapon_Spore1_0", + "Weapon_Spore1_1", + "Weapon_Spore1_2", + "Weapon_Spore1_3", + "Weapon_Spore1_4", + "Weapon_Spore2_0", + "Weapon_Spore2_1", + "Weapon_Spore2_2", + "Weapon_Spore2_3", + "Weapon_Spore2_4" + ] + }, + { + "id": "w09", + "file": "unit_w09.glb", + "errors": [], + "warnings": [], + "triangles": 52040, + "mesh_parts": 199, + "primitives": 199, + "vertices": 27280, + "closed_meshes": 199, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Crown0", + "Head_Crown0_Midrib", + "Head_Crown0_Vein0_1", + "Head_Crown0_Vein0__1", + "Head_Crown0_Vein1_1", + "Head_Crown0_Vein1__1", + "Head_Crown0_Vein2_1", + "Head_Crown0_Vein2__1", + "Head_Crown1", + "Head_Crown1_Midrib", + "Head_Crown1_Vein0_1", + "Head_Crown1_Vein0__1", + "Head_Crown1_Vein1_1", + "Head_Crown1_Vein1__1", + "Head_Crown1_Vein2_1", + "Head_Crown1_Vein2__1", + "Head_Crown2", + "Head_Crown2_Midrib", + "Head_Crown2_Vein0_1", + "Head_Crown2_Vein0__1", + "Head_Crown2_Vein1_1", + "Head_Crown2_Vein1__1", + "Head_Crown2_Vein2_1", + "Head_Crown2_Vein2__1", + "Head_Crown3", + "Head_Crown3_Midrib", + "Head_Crown3_Vein0_1", + "Head_Crown3_Vein0__1", + "Head_Crown3_Vein1_1", + "Head_Crown3_Vein1__1", + "Head_Crown3_Vein2_1", + "Head_Crown3_Vein2__1", + "Head_Crown4", + "Head_Crown4_Midrib", + "Head_Crown4_Vein0_1", + "Head_Crown4_Vein0__1", + "Head_Crown4_Vein1_1", + "Head_Crown4_Vein1__1", + "Head_Crown4_Vein2_1", + "Head_Crown4_Vein2__1", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Basin_Rim", + "Weapon_Basin_Shell", + "Weapon_DewOrb", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_Water" + ] + }, + { + "id": "w10", + "file": "unit_w10.glb", + "errors": [], + "warnings": [], + "triangles": 61052, + "mesh_parts": 348, + "primitives": 348, + "vertices": 32421, + "closed_meshes": 348, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Arch1_0", + "Body_Arch1_0_Grain0", + "Body_Arch1_0_Grain1", + "Body_Arch1_0_Grain2", + "Body_Arch1_1", + "Body_Arch1_1_Grain0", + "Body_Arch1_1_Grain1", + "Body_Arch1_1_Grain2", + "Body_Arch1_2", + "Body_Arch1_2_Grain0", + "Body_Arch1_2_Grain1", + "Body_Arch1_2_Grain2", + "Body_Arch_1_0", + "Body_Arch_1_0_Grain0", + "Body_Arch_1_0_Grain1", + "Body_Arch_1_0_Grain2", + "Body_Arch_1_1", + "Body_Arch_1_1_Grain0", + "Body_Arch_1_1_Grain1", + "Body_Arch_1_1_Grain2", + "Body_Arch_1_2", + "Body_Arch_1_2_Grain0", + "Body_Arch_1_2_Grain1", + "Body_Arch_1_2_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_Blossom3_Pollen", + "Body_Blossom4_Petal0", + "Body_Blossom4_Petal1", + "Body_Blossom4_Petal2", + "Body_Blossom4_Petal3", + "Body_Blossom4_Petal4", + "Body_Blossom4_Pollen", + "Body_Blossom5_Petal0", + "Body_Blossom5_Petal1", + "Body_Blossom5_Petal2", + "Body_Blossom5_Petal3", + "Body_Blossom5_Petal4", + "Body_Blossom5_Pollen", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy11", + "Head_Canopy11_Midrib", + "Head_Canopy11_Vein0_1", + "Head_Canopy11_Vein0__1", + "Head_Canopy11_Vein1_1", + "Head_Canopy11_Vein1__1", + "Head_Canopy11_Vein2_1", + "Head_Canopy11_Vein2__1", + "Head_Canopy12", + "Head_Canopy12_Midrib", + "Head_Canopy12_Vein0_1", + "Head_Canopy12_Vein0__1", + "Head_Canopy12_Vein1_1", + "Head_Canopy12_Vein1__1", + "Head_Canopy12_Vein2_1", + "Head_Canopy12_Vein2__1", + "Head_Canopy13", + "Head_Canopy13_Midrib", + "Head_Canopy13_Vein0_1", + "Head_Canopy13_Vein0__1", + "Head_Canopy13_Vein1_1", + "Head_Canopy13_Vein1__1", + "Head_Canopy13_Vein2_1", + "Head_Canopy13_Vein2__1", + "Head_Canopy14", + "Head_Canopy14_Midrib", + "Head_Canopy14_Vein0_1", + "Head_Canopy14_Vein0__1", + "Head_Canopy14_Vein1_1", + "Head_Canopy14_Vein1__1", + "Head_Canopy14_Vein2_1", + "Head_Canopy14_Vein2__1", + "Head_Canopy15", + "Head_Canopy15_Midrib", + "Head_Canopy15_Vein0_1", + "Head_Canopy15_Vein0__1", + "Head_Canopy15_Vein1_1", + "Head_Canopy15_Vein1__1", + "Head_Canopy15_Vein2_1", + "Head_Canopy15_Vein2__1", + "Head_Canopy16", + "Head_Canopy16_Midrib", + "Head_Canopy16_Vein0_1", + "Head_Canopy16_Vein0__1", + "Head_Canopy16_Vein1_1", + "Head_Canopy16_Vein1__1", + "Head_Canopy16_Vein2_1", + "Head_Canopy16_Vein2__1", + "Head_Canopy17", + "Head_Canopy17_Midrib", + "Head_Canopy17_Vein0_1", + "Head_Canopy17_Vein0__1", + "Head_Canopy17_Vein1_1", + "Head_Canopy17_Vein1__1", + "Head_Canopy17_Vein2_1", + "Head_Canopy17_Vein2__1", + "Head_Canopy18", + "Head_Canopy18_Midrib", + "Head_Canopy18_Vein0_1", + "Head_Canopy18_Vein0__1", + "Head_Canopy18_Vein1_1", + "Head_Canopy18_Vein1__1", + "Head_Canopy18_Vein2_1", + "Head_Canopy18_Vein2__1", + "Head_Canopy19", + "Head_Canopy19_Midrib", + "Head_Canopy19_Vein0_1", + "Head_Canopy19_Vein0__1", + "Head_Canopy19_Vein1_1", + "Head_Canopy19_Vein1__1", + "Head_Canopy19_Vein2_1", + "Head_Canopy19_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy20", + "Head_Canopy20_Midrib", + "Head_Canopy20_Vein0_1", + "Head_Canopy20_Vein0__1", + "Head_Canopy20_Vein1_1", + "Head_Canopy20_Vein1__1", + "Head_Canopy20_Vein2_1", + "Head_Canopy20_Vein2__1", + "Head_Canopy21", + "Head_Canopy21_Midrib", + "Head_Canopy21_Vein0_1", + "Head_Canopy21_Vein0__1", + "Head_Canopy21_Vein1_1", + "Head_Canopy21_Vein1__1", + "Head_Canopy21_Vein2_1", + "Head_Canopy21_Vein2__1", + "Head_Canopy22", + "Head_Canopy22_Midrib", + "Head_Canopy22_Vein0_1", + "Head_Canopy22_Vein0__1", + "Head_Canopy22_Vein1_1", + "Head_Canopy22_Vein1__1", + "Head_Canopy22_Vein2_1", + "Head_Canopy22_Vein2__1", + "Head_Canopy23", + "Head_Canopy23_Midrib", + "Head_Canopy23_Vein0_1", + "Head_Canopy23_Vein0__1", + "Head_Canopy23_Vein1_1", + "Head_Canopy23_Vein1__1", + "Head_Canopy23_Vein2_1", + "Head_Canopy23_Vein2__1", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Basin_Rim", + "Weapon_Basin_Shell", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_Water" + ] + }, + { + "id": "s01", + "file": "unit_s01.glb", + "errors": [], + "warnings": [], + "triangles": 10340, + "mesh_parts": 34, + "primitives": 34, + "vertices": 8466, + "closed_meshes": 34, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_DiagonalBelt", + "Body_LeatherCuirass", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Scarf", + "Body_SplitCoat1", + "Body_SplitCoat_1", + "Body_TornScarf1", + "Body_TornScarf_1", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_Bolt", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_CrossbowStock", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "s02", + "file": "unit_s02.glb", + "errors": [], + "warnings": [], + "triangles": 12040, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9256, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Corner10_4", + "Weapon_Corner11_16", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_ShieldBoss", + "Weapon_ShieldSpine", + "Weapon_TowerShield_Face", + "Weapon_TowerShield_Rim" + ] + }, + { + "id": "s03", + "file": "unit_s03.glb", + "errors": [], + "warnings": [], + "triangles": 7832, + "mesh_parts": 19, + "primitives": 19, + "vertices": 6089, + "closed_meshes": 19, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_CreamStole1", + "Body_CreamStole_1", + "Body_LongRobe", + "Body_RaggedCloak1", + "Body_RaggedCloak_1", + "Body_Scarf", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "Weapon_Trumpet" + ] + }, + { + "id": "s04", + "file": "unit_s04.glb", + "errors": [], + "warnings": [], + "triangles": 10458, + "mesh_parts": 35, + "primitives": 35, + "vertices": 8062, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Haft", + "Weapon_Head", + "Weapon_TriangleInset", + "Weapon_TriangleRim", + "Weapon_Wedge" + ] + }, + { + "id": "s05", + "file": "unit_s05.glb", + "errors": [], + "warnings": [], + "triangles": 10440, + "mesh_parts": 31, + "primitives": 31, + "vertices": 8279, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_HipRag1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_HollowRib_1", + "Body_RiftEdge1", + "Body_RiftEdge_1", + "Body_TornCloth1", + "Body_TornCloth_1", + "Head_Antler1", + "Head_Antler_1", + "Head_FacelessHelm", + "Head_InnerHorn1", + "Head_InnerHorn_1", + "Head_MintCrack", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_RiftLight", + "Weapon_RiftOrb" + ] + }, + { + "id": "worker", + "file": "worker.glb", + "errors": [], + "warnings": [], + "triangles": 24026, + "mesh_parts": 65, + "primitives": 65, + "vertices": 15341, + "closed_meshes": 65, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Glove", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Glove", + "ArmR_Upper", + "Body_ApronRivet0", + "Body_ApronRivet1", + "Body_ApronRivet2", + "Body_ApronRivet3", + "Body_ApronRivet4", + "Body_ApronRivet5", + "Body_ApronRivet6", + "Body_ClayTorso", + "Body_Harness1", + "Body_Harness_1", + "Body_LeatherApron", + "Body_Reservoir", + "Body_TankBrace0", + "Body_TankBrace1", + "Body_TankBrace2", + "Body_TankBrace3", + "Body_TankBrace4", + "Body_TankBrace5", + "Body_TankBrace6", + "Body_TankBrace7", + "Body_TankRim0_45", + "Body_TankRim0_79", + "Body_ToolPocket", + "Head_Cap", + "Head_FaceRecess", + "Head_GoggleGlint1", + "Head_GoggleGlint_1", + "Head_GoggleLens1", + "Head_GoggleLens_1", + "Head_GoggleSocket1", + "Head_GoggleSocket_1", + "Head_Hood", + "Head_Lamp", + "Head_LampHousing", + "LegL_Boot", + "LegL_Cuff", + "LegL_Shin", + "LegL_Sole", + "LegL_ToeRidge0", + "LegL_ToeRidge1", + "LegL_ToeRidge2", + "LegR_Boot", + "LegR_Cuff", + "LegR_Shin", + "LegR_Sole", + "LegR_ToeRidge0", + "LegR_ToeRidge1", + "LegR_ToeRidge2", + "WeaponL_Fork", + "WeaponL_Handle", + "WeaponR_Probe" + ] + }, + { + "id": "map_lane_segment", + "file": "map_lane_segment.glb", + "errors": [], + "warnings": [], + "triangles": 10700, + "mesh_parts": 45, + "primitives": 45, + "vertices": 8523, + "closed_meshes": 45, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeCap1_0", + "Body_EdgeCap1_1", + "Body_EdgeCap1_2", + "Body_EdgeCap1_3", + "Body_EdgeCap_1_0", + "Body_EdgeCap_1_1", + "Body_EdgeCap_1_2", + "Body_EdgeCap_1_3", + "Body_EdgeStone1_0", + "Body_EdgeStone1_1", + "Body_EdgeStone1_2", + "Body_EdgeStone1_3", + "Body_EdgeStone_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeStone_1_3", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_LRetainingLip", + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LightGlass1_0", + "Body_LightGlass1_1", + "Body_LightGlass_1_0", + "Body_LightGlass_1_1", + "Body_LightRecess1_0", + "Body_LightRecess1_1", + "Body_LightRecess_1_0", + "Body_LightRecess_1_1", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Body_RRetainingLip" + ] + }, + { + "id": "core_team0", + "file": "core_team0.glb", + "errors": [], + "warnings": [], + "triangles": 36652, + "mesh_parts": 64, + "primitives": 64, + "vertices": 21442, + "closed_meshes": 64, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CoreStep0", + "Body_CoreStep1", + "Body_CoreStep2", + "Body_CoreStep3", + "Body_CoreStepRim0", + "Body_CoreStepRim1", + "Body_CoreStepRim2", + "Body_CoreStepRim3", + "Body_Cradle0", + "Body_Cradle1", + "Body_Cradle2", + "Body_Cradle3", + "Body_Cradle4", + "Body_Cradle5", + "Body_CradleCollar0", + "Body_CradleCollar1", + "Body_CradleCollar2", + "Body_CradleCollar3", + "Body_CradleCollar4", + "Body_CradleCollar5", + "Body_CrystalHalo", + "Body_PlinthBlock0", + "Body_PlinthBlock1", + "Body_PlinthBlock10", + "Body_PlinthBlock11", + "Body_PlinthBlock2", + "Body_PlinthBlock3", + "Body_PlinthBlock4", + "Body_PlinthBlock5", + "Body_PlinthBlock6", + "Body_PlinthBlock7", + "Body_PlinthBlock8", + "Body_PlinthBlock9", + "Body_RadialInlay0", + "Body_RadialInlay1", + "Body_RadialInlay10", + "Body_RadialInlay11", + "Body_RadialInlay2", + "Body_RadialInlay3", + "Body_RadialInlay4", + "Body_RadialInlay5", + "Body_RadialInlay6", + "Body_RadialInlay7", + "Body_RadialInlay8", + "Body_RadialInlay9", + "Body_Seal0", + "Body_Seal1", + "Body_Seal10", + "Body_Seal11", + "Body_Seal2", + "Body_Seal3", + "Body_Seal4", + "Body_Seal5", + "Body_Seal6", + "Body_Seal7", + "Body_Seal8", + "Body_Seal9", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Team_Circle" + ] + }, + { + "id": "core_team1", + "file": "core_team1.glb", + "errors": [], + "warnings": [], + "triangles": 36848, + "mesh_parts": 66, + "primitives": 66, + "vertices": 21609, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CoreStep0", + "Body_CoreStep1", + "Body_CoreStep2", + "Body_CoreStep3", + "Body_CoreStepRim0", + "Body_CoreStepRim1", + "Body_CoreStepRim2", + "Body_CoreStepRim3", + "Body_Cradle0", + "Body_Cradle1", + "Body_Cradle2", + "Body_Cradle3", + "Body_Cradle4", + "Body_Cradle5", + "Body_CradleCollar0", + "Body_CradleCollar1", + "Body_CradleCollar2", + "Body_CradleCollar3", + "Body_CradleCollar4", + "Body_CradleCollar5", + "Body_CrystalHalo", + "Body_PlinthBlock0", + "Body_PlinthBlock1", + "Body_PlinthBlock10", + "Body_PlinthBlock11", + "Body_PlinthBlock2", + "Body_PlinthBlock3", + "Body_PlinthBlock4", + "Body_PlinthBlock5", + "Body_PlinthBlock6", + "Body_PlinthBlock7", + "Body_PlinthBlock8", + "Body_PlinthBlock9", + "Body_RadialInlay0", + "Body_RadialInlay1", + "Body_RadialInlay10", + "Body_RadialInlay11", + "Body_RadialInlay2", + "Body_RadialInlay3", + "Body_RadialInlay4", + "Body_RadialInlay5", + "Body_RadialInlay6", + "Body_RadialInlay7", + "Body_RadialInlay8", + "Body_RadialInlay9", + "Body_Seal0", + "Body_Seal1", + "Body_Seal10", + "Body_Seal11", + "Body_Seal2", + "Body_Seal3", + "Body_Seal4", + "Body_Seal5", + "Body_Seal6", + "Body_Seal7", + "Body_Seal8", + "Body_Seal9", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Team_Triangle0", + "Team_Triangle1", + "Team_Triangle2" + ] + }, + { + "id": "e01", + "file": "enemy_e01.glb", + "errors": [], + "warnings": [], + "triangles": 19228, + "mesh_parts": 38, + "primitives": 38, + "vertices": 13459, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e02", + "file": "enemy_e02.glb", + "errors": [], + "warnings": [], + "triangles": 20180, + "mesh_parts": 42, + "primitives": 42, + "vertices": 13943, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Body_Spine0", + "Body_Spine1", + "Body_Spine2", + "Body_Spine3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e03", + "file": "enemy_e03.glb", + "errors": [], + "warnings": [], + "triangles": 35898, + "mesh_parts": 69, + "primitives": 69, + "vertices": 23110, + "closed_meshes": 69, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_RiftHalo", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull" + ] + }, + { + "id": "e04", + "file": "enemy_e04.glb", + "errors": [], + "warnings": [], + "triangles": 51050, + "mesh_parts": 110, + "primitives": 110, + "vertices": 33310, + "closed_meshes": 110, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_Arrow", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "e05", + "file": "enemy_e05.glb", + "errors": [], + "warnings": [], + "triangles": 62798, + "mesh_parts": 125, + "primitives": 125, + "vertices": 40983, + "closed_meshes": 125, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0", + "ArmL_Knuckle1", + "ArmL_Knuckle2", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_StoneHammer", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Cuff", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0", + "ArmR_Knuckle1", + "ArmR_Knuckle2", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_StoneHammer", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_BackSlab0", + "Body_BackSlab1", + "Body_BackSlab2", + "Body_BackSlab3", + "Body_BruteCore", + "Body_Chest0_1", + "Body_Chest0__1", + "Body_Chest1_1", + "Body_Chest1__1", + "Body_Chest2_1", + "Body_Chest2__1", + "Body_RiftCrack", + "Body_ShoulderSpikeL0", + "Body_ShoulderSpikeL1", + "Body_ShoulderSpikeL2", + "Body_ShoulderSpikeR0", + "Body_ShoulderSpikeR1", + "Body_ShoulderSpikeR2", + "Head_Mask_EyeLight1", + "Head_Mask_EyeLight_1", + "Head_Mask_EyeSocket1", + "Head_Mask_EyeSocket_1", + "Head_Mask_MouthSlit0", + "Head_Mask_MouthSlit1", + "Head_Mask_MouthSlit2", + "Head_Mask_Nose", + "Head_Mask_Porcelain", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e06", + "file": "enemy_e06.glb", + "errors": [], + "warnings": [], + "triangles": 48336, + "mesh_parts": 84, + "primitives": 84, + "vertices": 29712, + "closed_meshes": 84, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HealingKnot0", + "Body_HealingKnot1", + "Body_HealingKnot2", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e07", + "file": "enemy_e07.glb", + "errors": [], + "warnings": [], + "triangles": 33800, + "mesh_parts": 49, + "primitives": 49, + "vertices": 20343, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "Body_DeerCore", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_Tail", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_AntlerR", + "Head_EyeL", + "Head_EyeR", + "Head_Muzzle", + "Head_Neck", + "Head_Nose", + "Head_Skull", + "LegL0_ClovenLine", + "LegL0_Hoof", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_ClovenLine", + "LegL1_Hoof", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Upper", + "LegR0_ClovenLine", + "LegR0_Hoof", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_ClovenLine", + "LegR1_Hoof", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Upper" + ] + }, + { + "id": "e08", + "file": "enemy_e08.glb", + "errors": [], + "warnings": [], + "triangles": 81240, + "mesh_parts": 222, + "primitives": 222, + "vertices": 54311, + "closed_meshes": 222, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_RiftHorn1", + "Body_RiftHorn_1", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e09", + "file": "enemy_e09.glb", + "errors": [], + "warnings": [], + "triangles": 57310, + "mesh_parts": 135, + "primitives": 135, + "vertices": 35714, + "closed_meshes": 135, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_Chains1", + "Body_Chains_1", + "Body_CourtMask0_EyeLight1", + "Body_CourtMask0_EyeLight_1", + "Body_CourtMask0_EyeSocket1", + "Body_CourtMask0_EyeSocket_1", + "Body_CourtMask0_MouthSlit0", + "Body_CourtMask0_MouthSlit1", + "Body_CourtMask0_MouthSlit2", + "Body_CourtMask0_Nose", + "Body_CourtMask0_Porcelain", + "Body_CourtMask1_EyeLight1", + "Body_CourtMask1_EyeLight_1", + "Body_CourtMask1_EyeSocket1", + "Body_CourtMask1_EyeSocket_1", + "Body_CourtMask1_MouthSlit0", + "Body_CourtMask1_MouthSlit1", + "Body_CourtMask1_MouthSlit2", + "Body_CourtMask1_Nose", + "Body_CourtMask1_Porcelain", + "Body_CourtMask2_EyeLight1", + "Body_CourtMask2_EyeLight_1", + "Body_CourtMask2_EyeSocket1", + "Body_CourtMask2_EyeSocket_1", + "Body_CourtMask2_MouthSlit0", + "Body_CourtMask2_MouthSlit1", + "Body_CourtMask2_MouthSlit2", + "Body_CourtMask2_Nose", + "Body_CourtMask2_Porcelain", + "Body_CourtMask3_EyeLight1", + "Body_CourtMask3_EyeLight_1", + "Body_CourtMask3_EyeSocket1", + "Body_CourtMask3_EyeSocket_1", + "Body_CourtMask3_MouthSlit0", + "Body_CourtMask3_MouthSlit1", + "Body_CourtMask3_MouthSlit2", + "Body_CourtMask3_Nose", + "Body_CourtMask3_Porcelain", + "Body_CourtMask4_EyeLight1", + "Body_CourtMask4_EyeLight_1", + "Body_CourtMask4_EyeSocket1", + "Body_CourtMask4_EyeSocket_1", + "Body_CourtMask4_MouthSlit0", + "Body_CourtMask4_MouthSlit1", + "Body_CourtMask4_MouthSlit2", + "Body_CourtMask4_Nose", + "Body_CourtMask4_Porcelain", + "Body_CrownSpike0", + "Body_CrownSpike1", + "Body_CrownSpike2", + "Body_CrownSpike3", + "Body_CrownSpike4", + "Body_JudgeGlow", + "Body_JudgeHalo", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e10", + "file": "enemy_e10.glb", + "errors": [], + "warnings": [], + "triangles": 64694, + "mesh_parts": 82, + "primitives": 82, + "vertices": 37825, + "closed_meshes": 82, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrownCore", + "Body_RidgeL0", + "Body_RidgeL1", + "Body_RidgeL2", + "Body_RidgeL3", + "Body_RidgeR0", + "Body_RidgeR1", + "Body_RidgeR2", + "Body_RidgeR3", + "Body_ShellL0", + "Body_ShellL1", + "Body_ShellL2", + "Body_ShellL3", + "Body_ShellR0", + "Body_ShellR1", + "Body_ShellR2", + "Body_ShellR3", + "Body_Tail", + "Head_Brow1", + "Head_Brow_1", + "Head_CrownBand", + "Head_CrownGem0", + "Head_CrownGem1", + "Head_CrownGem2", + "Head_CrownGem3", + "Head_CrownGem4", + "Head_CrownGem5", + "Head_CrownGem6", + "Head_CrownPoint0", + "Head_CrownPoint1", + "Head_CrownPoint2", + "Head_CrownPoint3", + "Head_CrownPoint4", + "Head_CrownPoint5", + "Head_CrownPoint6", + "Head_Eye1", + "Head_Eye_1", + "Head_MawRim", + "Head_MawVoid", + "Head_RiftThroat", + "Head_Tooth0", + "Head_Tooth1", + "Head_Tooth10", + "Head_Tooth11", + "Head_Tooth12", + "Head_Tooth13", + "Head_Tooth2", + "Head_Tooth3", + "Head_Tooth4", + "Head_Tooth5", + "Head_Tooth6", + "Head_Tooth7", + "Head_Tooth8", + "Head_Tooth9", + "LegL0_Claw0", + "LegL0_Claw1", + "LegL0_Claw2", + "LegL0_Inner", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Thigh", + "LegL1_Claw0", + "LegL1_Claw1", + "LegL1_Claw2", + "LegL1_Inner", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Thigh", + "LegR0_Claw0", + "LegR0_Claw1", + "LegR0_Claw2", + "LegR0_Inner", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Thigh", + "LegR1_Claw0", + "LegR1_Claw1", + "LegR1_Claw2", + "LegR1_Inner", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Thigh" + ] + } + ], + "upgrade_pairs": [ + { + "base": "g01", + "upgrade": "g02", + "structurally_distinct": true + }, + { + "base": "g03", + "upgrade": "g04", + "structurally_distinct": true + }, + { + "base": "g05", + "upgrade": "g06", + "structurally_distinct": true + }, + { + "base": "g07", + "upgrade": "g08", + "structurally_distinct": true + }, + { + "base": "g09", + "upgrade": "g10", + "structurally_distinct": true + }, + { + "base": "m01", + "upgrade": "m02", + "structurally_distinct": true + }, + { + "base": "m03", + "upgrade": "m04", + "structurally_distinct": true + }, + { + "base": "m05", + "upgrade": "m06", + "structurally_distinct": true + }, + { + "base": "m07", + "upgrade": "m08", + "structurally_distinct": true + }, + { + "base": "m09", + "upgrade": "m10", + "structurally_distinct": true + }, + { + "base": "n01", + "upgrade": "n02", + "structurally_distinct": true + }, + { + "base": "n03", + "upgrade": "n04", + "structurally_distinct": true + }, + { + "base": "n05", + "upgrade": "n06", + "structurally_distinct": true + }, + { + "base": "n07", + "upgrade": "n08", + "structurally_distinct": true + }, + { + "base": "n09", + "upgrade": "n10", + "structurally_distinct": true + }, + { + "base": "w01", + "upgrade": "w02", + "structurally_distinct": true + }, + { + "base": "w03", + "upgrade": "w04", + "structurally_distinct": true + }, + { + "base": "w05", + "upgrade": "w06", + "structurally_distinct": true + }, + { + "base": "w07", + "upgrade": "w08", + "structurally_distinct": true + }, + { + "base": "w09", + "upgrade": "w10", + "structurally_distinct": true + } + ], + "passed": true, + "warning_count": 0 +} diff --git a/docs/phase10-logs/art-delivery.log b/docs/phase10-logs/art-delivery.log new file mode 100644 index 0000000..7652ca3 --- /dev/null +++ b/docs/phase10-logs/art-delivery.log @@ -0,0 +1,12 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +ART_CAPTURE: menu +ART_CAPTURE: build +ART_CAPTURE: base +ART_CAPTURE: model-w04 +ART_CAPTURE: model-w08 +ART_CAPTURE: model-w10 +ART_CAPTURE: model-g02 +ART_CAPTURE: model-g04 +ART_CAPTURE: map-overview diff --git a/docs/phase10-logs/art-final.log b/docs/phase10-logs/art-final.log new file mode 100644 index 0000000..7652ca3 --- /dev/null +++ b/docs/phase10-logs/art-final.log @@ -0,0 +1,12 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +ART_CAPTURE: menu +ART_CAPTURE: build +ART_CAPTURE: base +ART_CAPTURE: model-w04 +ART_CAPTURE: model-w08 +ART_CAPTURE: model-w10 +ART_CAPTURE: model-g02 +ART_CAPTURE: model-g04 +ART_CAPTURE: map-overview diff --git a/docs/phase10-logs/art-review.log b/docs/phase10-logs/art-review.log new file mode 100644 index 0000000..7652ca3 --- /dev/null +++ b/docs/phase10-logs/art-review.log @@ -0,0 +1,12 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +ART_CAPTURE: menu +ART_CAPTURE: build +ART_CAPTURE: base +ART_CAPTURE: model-w04 +ART_CAPTURE: model-w08 +ART_CAPTURE: model-w10 +ART_CAPTURE: model-g02 +ART_CAPTURE: model-g04 +ART_CAPTURE: map-overview diff --git a/docs/phase10-logs/bark-bake.log b/docs/phase10-logs/bark-bake.log new file mode 100644 index 0000000..1b9368f --- /dev/null +++ b/docs/phase10-logs/bark-bake.log @@ -0,0 +1,12 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase10/bake_bark.py:17: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new('SW_4K_Sculpted_Oak');mat.use_nodes=True;plane.data.materials.append(mat) +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) +[OpenColorIO Info]: Color management disabled. (Specify the $OCIO environment variable to enable.) +01:04.108 render | Saved: '/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/materials/phase10/oak-height-4k.png' +02:09.912 render | Saved: '/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/materials/phase10/oak-albedo-4k.png' +PBR_BAKE_PASS: two native 4096 x 4096 16-bit maps; original seamless procedural material. + +Blender quit diff --git a/docs/phase10-logs/builds.log b/docs/phase10-logs/builds.log new file mode 100644 index 0000000..c1eccb0 --- /dev/null +++ b/docs/phase10-logs/builds.log @@ -0,0 +1,2 @@ +Linux: Saumwacht-Linux-x64-0.10.0.zip (174.8 MiB) +Windows: Saumwacht-Windows-x64-0.10.0.zip (184.3 MiB) diff --git a/docs/phase10-logs/environment-build.log b/docs/phase10-logs/environment-build.log new file mode 100644 index 0000000..33e5e68 --- /dev/null +++ b/docs/phase10-logs/environment-build.log @@ -0,0 +1,141 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase10/build_sanctuary.py:30: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new('ENV_'+key); mat.use_nodes=True +Warnung: Keine Maschendaten zum verknüpfen +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +23:07:23 | INFO: Starting glTF 2.0 export +23:07:23 | INFO: Extracting primitive: Cube +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Causeway_Foundation_Mesh.001 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Boundary_Inlay_Mesh.015 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_1_Spray_1_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_1_Spray_0_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_1_Canopy_0_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Edge_Coping_Mesh.045 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Paving_Mesh.132 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Sculpted_River_Gorge_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Pillar_Foot_Mesh.004 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Stratified_Cliff_Mesh.022 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Boundary_Inlay_Mesh.014 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Edge_Coping_Mesh.042 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Paving_Mesh.120 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Stratified_Cliff_Mesh.028 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Boundary_Inlay_Mesh.018 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Edge_Coping_Mesh.053 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Paving_Mesh.180 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Sanctum_Inlay_Mesh.002 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Stratified_Cliff_Mesh.032 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Pillar_Inscription_Mesh.024 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Edge_Coping_Mesh.061 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Paving_Mesh.228 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_1_Root_5_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Forest_Boulder_Mesh.002 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Fallen_Ruin_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_1_Trunk_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Forest_Boulder_Mesh.004 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Fallen_Ruin_Mesh.006 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_13_Trunk_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Forest_Boulder_Mesh.001 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Fallen_Ruin_Mesh.024 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Tree_5_Trunk_Mesh +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Forest_Boulder_Mesh.003 +23:07:23 | INFO: Primitives created: 1 +23:07:23 | INFO: Extracting primitive: Fallen_Ruin_Mesh.012 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Causeway_Foundation_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Edge_Coping_Mesh.003 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Paving_Mesh.012 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Boundary_Inlay_Mesh.001 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Pillar_Foot_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Stratified_Cliff_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Edge_Coping_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Paving_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Boundary_Inlay_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Stratified_Cliff_Mesh.006 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Edge_Coping_Mesh.011 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Paving_Mesh.060 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Boundary_Inlay_Mesh.004 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Sanctum_Inlay_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Stratified_Cliff_Mesh.010 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Edge_Coping_Mesh.019 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Paving_Mesh.108 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Pillar_Inscription_Mesh.008 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Tree_2_Root_1_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Forest_Boulder_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Fallen_Ruin_Mesh.021 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Tree_6_Root_2_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Forest_Boulder_Mesh.012 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Tree_2_Trunk_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Forest_Boulder_Mesh.005 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Tree_14_Trunk_Mesh +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Forest_Boulder_Mesh.006 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Extracting primitive: Fallen_Ruin_Mesh.018 +23:07:24 | INFO: Primitives created: 1 +23:07:24 | INFO: Finished glTF 2.0 export in 0.9540770053863525 s + +ENVIRONMENT_EXPORTED {"name": "Die gr\u00fcne Kluft", "source_objects": 2585, "runtime_chunks": 62, "triangles": 1136648, "seed": 10092026, "blender": "5.2.1 LTS", "sha256": "546ff97de9522cdbb677b2273cd66df09b65c21e6b03723cbc2005fdcfa518f0", "playable_grids": 2, "cell_size_m": 2, "grid_cells": [6, 8]} +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/environment-final-build.log b/docs/phase10-logs/environment-final-build.log new file mode 100644 index 0000000..a2ab156 --- /dev/null +++ b/docs/phase10-logs/environment-final-build.log @@ -0,0 +1,141 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase10/build_sanctuary.py:30: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new('ENV_'+key); mat.use_nodes=True +Warnung: Keine Maschendaten zum verknüpfen +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:46:12 | INFO: Starting glTF 2.0 export +20:46:12 | INFO: Extracting primitive: Cube +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Causeway_Foundation_Mesh.001 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh.015 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_1_Spray_1_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_1_Spray_0_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_1_Canopy_0_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.045 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.132 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Sculpted_River_Gorge_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Pillar_Foot_Mesh.004 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh.022 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh.014 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.042 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.120 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh.028 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh.018 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.053 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.180 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Sanctum_Inlay_Mesh.002 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh.032 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Pillar_Inscription_Mesh.024 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.061 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.228 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_1_Root_5_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Forest_Boulder_Mesh.002 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Fallen_Ruin_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_1_Trunk_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Forest_Boulder_Mesh.004 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Fallen_Ruin_Mesh.006 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_13_Trunk_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Forest_Boulder_Mesh.001 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Fallen_Ruin_Mesh.024 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Tree_5_Trunk_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Forest_Boulder_Mesh.003 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Fallen_Ruin_Mesh.012 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Causeway_Foundation_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.003 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.012 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh.001 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Pillar_Foot_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh.006 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.011 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.060 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Boundary_Inlay_Mesh.004 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Sanctum_Inlay_Mesh +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Stratified_Cliff_Mesh.010 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Edge_Coping_Mesh.019 +20:46:12 | INFO: Primitives created: 1 +20:46:12 | INFO: Extracting primitive: Paving_Mesh.108 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Pillar_Inscription_Mesh.008 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Tree_2_Root_1_Mesh +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Forest_Boulder_Mesh +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Fallen_Ruin_Mesh.021 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Tree_6_Root_2_Mesh +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Forest_Boulder_Mesh.012 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Tree_2_Trunk_Mesh +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Forest_Boulder_Mesh.005 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Tree_14_Trunk_Mesh +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Forest_Boulder_Mesh.006 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Extracting primitive: Fallen_Ruin_Mesh.018 +20:46:13 | INFO: Primitives created: 1 +20:46:13 | INFO: Finished glTF 2.0 export in 1.2319343090057373 s + +ENVIRONMENT_EXPORTED {"name": "Die gr\u00fcne Kluft", "source_objects": 2586, "runtime_chunks": 62, "triangles": 1509472, "seed": 10092026, "blender": "5.2.1 LTS", "sha256": "b43087a69dd48db00864ac2bb35d5d6872b27d405d8d5f1012f713c2b4092f09", "playable_grids": 2, "cell_size_m": 2, "grid_cells": [6, 8]} +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/environment-shores.log b/docs/phase10-logs/environment-shores.log new file mode 100644 index 0000000..c956f1a --- /dev/null +++ b/docs/phase10-logs/environment-shores.log @@ -0,0 +1,141 @@ +00:00.016 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.016 color_management | Using fallback mode for management +/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase10/build_sanctuary.py:30: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new('ENV_'+key); mat.use_nodes=True +Warnung: Keine Maschendaten zum verknüpfen +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:50:21 | INFO: Starting glTF 2.0 export +20:50:21 | INFO: Extracting primitive: Cube +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Causeway_Foundation_Mesh.001 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Boundary_Inlay_Mesh.015 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Tree_1_Spray_1_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Tree_1_Spray_0_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Tree_1_Canopy_0_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Edge_Coping_Mesh.045 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Paving_Mesh.132 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Sculpted_River_Gorge_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Pillar_Foot_Mesh.004 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Stratified_Cliff_Mesh.022 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Boundary_Inlay_Mesh.014 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Edge_Coping_Mesh.042 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Paving_Mesh.120 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Stratified_Cliff_Mesh.028 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Boundary_Inlay_Mesh.018 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Edge_Coping_Mesh.053 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Paving_Mesh.180 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Sanctum_Inlay_Mesh.002 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Stratified_Cliff_Mesh.032 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Pillar_Inscription_Mesh.024 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Edge_Coping_Mesh.061 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Paving_Mesh.228 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Tree_1_Root_5_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Forest_Boulder_Mesh.002 +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Fallen_Ruin_Mesh +20:50:21 | INFO: Primitives created: 1 +20:50:21 | INFO: Extracting primitive: Tree_1_Trunk_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.004 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Fallen_Ruin_Mesh.006 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_13_Trunk_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.001 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Fallen_Ruin_Mesh.024 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_5_Trunk_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.003 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Fallen_Ruin_Mesh.012 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Causeway_Foundation_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Edge_Coping_Mesh.003 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Paving_Mesh.012 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Boundary_Inlay_Mesh.001 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Pillar_Foot_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Stratified_Cliff_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Edge_Coping_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Paving_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Boundary_Inlay_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Stratified_Cliff_Mesh.006 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Edge_Coping_Mesh.011 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Paving_Mesh.060 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Boundary_Inlay_Mesh.004 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Sanctum_Inlay_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Stratified_Cliff_Mesh.010 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Edge_Coping_Mesh.019 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Paving_Mesh.108 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Pillar_Inscription_Mesh.008 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_2_Root_1_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Fallen_Ruin_Mesh.021 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_6_Root_2_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.012 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_2_Trunk_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.005 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Tree_14_Trunk_Mesh +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Forest_Boulder_Mesh.006 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Extracting primitive: Fallen_Ruin_Mesh.018 +20:50:22 | INFO: Primitives created: 1 +20:50:22 | INFO: Finished glTF 2.0 export in 1.284172534942627 s + +ENVIRONMENT_EXPORTED {"name": "Die gr\u00fcne Kluft", "source_objects": 2586, "runtime_chunks": 62, "triangles": 1607600, "seed": 10092026, "blender": "5.2.1 LTS", "sha256": "bebe2d4193500df1cf54970adf0e240607430d66e42fd9ab2e67368166a6d052", "playable_grids": 2, "cell_size_m": 2, "grid_cells": [6, 8]} +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/faction.log b/docs/phase10-logs/faction.log new file mode 100644 index 0000000..a997ce8 --- /dev/null +++ b/docs/phase10-logs/faction.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/sw10-faction/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/finalize-sources.log b/docs/phase10-logs/finalize-sources.log new file mode 100644 index 0000000..5ed44e1 --- /dev/null +++ b/docs/phase10-logs/finalize-sources.log @@ -0,0 +1,8 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +BLENDER_PBR_SOURCE_PASS: 33 independent scenes with editable high-resolution geometry and material nodes. +ENVIRONMENT_PBR_SOURCE_PASS +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/full-visual.log b/docs/phase10-logs/full-visual.log new file mode 100644 index 0000000..944aea6 --- /dev/null +++ b/docs/phase10-logs/full-visual.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1684 checks; 0 failures; /tmp/sw10-full-visual/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/import-final.log b/docs/phase10-logs/import-final.log new file mode 100644 index 0000000..adebe95 --- /dev/null +++ b/docs/phase10-logs/import-final.log @@ -0,0 +1,176 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] update_scripts_classes | Started Globale Klassen registrieren … (2 steps) +[ 0% ] update_scripts_classes |  +[ 33% ] update_scripts_classes |  +[ DONE ] update_scripts_classes + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (20 steps) +[ 0% ] _update_scan_actions | verdant-rift.glb +[ 4% ] _update_scan_actions | unit_w01.glb +[ 9% ] _update_scan_actions | unit_w02.glb +[ 14% ] _update_scan_actions | unit_w03.glb +[ 19% ] _update_scan_actions | unit_w04.glb +[ 23% ] _update_scan_actions | unit_w05.glb +[ 28% ] _update_scan_actions | unit_w06.glb +[ 33% ] _update_scan_actions | unit_w07.glb +[ 38% ] _update_scan_actions | unit_w08.glb +[ 42% ] _update_scan_actions | unit_w09.glb +[ 47% ] _update_scan_actions | unit_w10.glb +[ 52% ] _update_scan_actions | base.png +[ 57% ] _update_scan_actions | build.png +[ 61% ] _update_scan_actions | map-overview.png +[ 66% ] _update_scan_actions | menu.png +[ 71% ] _update_scan_actions | model-g02.png +[ 76% ] _update_scan_actions | model-g04.png +[ 80% ] _update_scan_actions | model-w04.png +[ 85% ] _update_scan_actions | model-w08.png +[ 90% ] _update_scan_actions | model-w10.png +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (20 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 4% ] reimport | Dateien zum Neuimport vorbereiten … +[ 9% ] reimport | Dateien zum Neuimport vorbereiten … +[ 14% ] reimport | Dateien zum Neuimport vorbereiten … +[ 19% ] reimport | Dateien zum Neuimport vorbereiten … +[ 23% ] reimport | Dateien zum Neuimport vorbereiten … +[ 28% ] reimport | Dateien zum Neuimport vorbereiten … +[ 33% ] reimport | Dateien zum Neuimport vorbereiten … +[ 38% ] reimport | Dateien zum Neuimport vorbereiten … +[ 42% ] reimport | Dateien zum Neuimport vorbereiten … +[ 47% ] reimport | Dateien zum Neuimport vorbereiten … +[ 52% ] reimport | Dateien zum Neuimport vorbereiten … +[ 57% ] reimport | Dateien zum Neuimport vorbereiten … +[ 61% ] reimport | Dateien zum Neuimport vorbereiten … +[ 66% ] reimport | Dateien zum Neuimport vorbereiten … +[ 71% ] reimport | Dateien zum Neuimport vorbereiten … +[ 76% ] reimport | Dateien zum Neuimport vorbereiten … +[ 80% ] reimport | Dateien zum Neuimport vorbereiten … +[ 85% ] reimport | Dateien zum Neuimport vorbereiten … +[ 90% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] preload_reimporting_scene | Started Szenen zum Neuladen vorbereiten (1 steps) +[ 0% ] preload_reimporting_scene | Szene [leer] wird analysiert +[ 50% ] preload_reimporting_scene | Vorbereitung abgeschlossen. +[ DONE ] preload_reimporting_scene + +[ 0% ] reimport | model-w10.png +[ 4% ] reimport | model-w08.png +[ 9% ] reimport | model-w04.png +[ 14% ] reimport | model-g04.png +[ 19% ] reimport | model-g02.png +[ 23% ] reimport | menu.png +[ 28% ] reimport | map-overview.png +[ 33% ] reimport | build.png +[ 38% ] reimport | base.png +[ 42% ] reimport | unit_w10.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 47% ] reimport | unit_w09.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 52% ] reimport | unit_w08.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 57% ] reimport | unit_w07.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 61% ] reimport | unit_w06.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 66% ] reimport | unit_w05.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 71% ] reimport | unit_w04.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 76% ] reimport | unit_w03.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 80% ] reimport | unit_w02.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 85% ] reimport | unit_w01.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 90% ] reimport | verdant-rift.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 95% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (20 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase10-logs/import.log b/docs/phase10-logs/import.log new file mode 100644 index 0000000..0d0642c --- /dev/null +++ b/docs/phase10-logs/import.log @@ -0,0 +1,186 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] update_scripts_classes | Started Globale Klassen registrieren … (5 steps) +[ 0% ] update_scripts_classes |  +[ 16% ] update_scripts_classes |  +[ 33% ] update_scripts_classes |  +[ 50% ] update_scripts_classes |  +[ 66% ] update_scripts_classes |  +[ DONE ] update_scripts_classes + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (21 steps) +[ 0% ] _update_scan_actions | verdant-rift.glb +[ 4% ] _update_scan_actions | Cantarell-VF.otf +[ 9% ] _update_scan_actions | limestone-albedo.png +[ 13% ] _update_scan_actions | oak-height-4k.png +[ 18% ] _update_scan_actions | unit_w01.glb +[ 22% ] _update_scan_actions | unit_w02.glb +[ 27% ] _update_scan_actions | unit_w03.glb +[ 31% ] _update_scan_actions | unit_w04.glb +[ 36% ] _update_scan_actions | unit_w05.glb +[ 40% ] _update_scan_actions | unit_w06.glb +[ 45% ] _update_scan_actions | unit_w07.glb +[ 50% ] _update_scan_actions | unit_w08.glb +[ 54% ] _update_scan_actions | unit_w09.glb +[ 59% ] _update_scan_actions | unit_w10.glb +[ 63% ] _update_scan_actions | base.png +[ 68% ] _update_scan_actions | build.png +[ 72% ] _update_scan_actions | combat.png +[ 77% ] _update_scan_actions | economy.png +[ 81% ] _update_scan_actions | menu.png +[ 86% ] _update_scan_actions | minimum-window.png +[ 90% ] _update_scan_actions | selection.png +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (21 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 4% ] reimport | Dateien zum Neuimport vorbereiten … +[ 9% ] reimport | Dateien zum Neuimport vorbereiten … +[ 13% ] reimport | Dateien zum Neuimport vorbereiten … +[ 18% ] reimport | Dateien zum Neuimport vorbereiten … +[ 22% ] reimport | Dateien zum Neuimport vorbereiten … +[ 27% ] reimport | Dateien zum Neuimport vorbereiten … +[ 31% ] reimport | Dateien zum Neuimport vorbereiten … +[ 36% ] reimport | Dateien zum Neuimport vorbereiten … +[ 40% ] reimport | Dateien zum Neuimport vorbereiten … +[ 45% ] reimport | Dateien zum Neuimport vorbereiten … +[ 50% ] reimport | Dateien zum Neuimport vorbereiten … +[ 54% ] reimport | Dateien zum Neuimport vorbereiten … +[ 59% ] reimport | Dateien zum Neuimport vorbereiten … +[ 63% ] reimport | Dateien zum Neuimport vorbereiten … +[ 68% ] reimport | Dateien zum Neuimport vorbereiten … +[ 72% ] reimport | Dateien zum Neuimport vorbereiten … +[ 77% ] reimport | Dateien zum Neuimport vorbereiten … +[ 81% ] reimport | Dateien zum Neuimport vorbereiten … +[ 86% ] reimport | Dateien zum Neuimport vorbereiten … +[ 90% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] preload_reimporting_scene | Started Szenen zum Neuladen vorbereiten (1 steps) +[ 0% ] preload_reimporting_scene | Szene [leer] wird analysiert +[ 50% ] preload_reimporting_scene | Vorbereitung abgeschlossen. +[ DONE ] preload_reimporting_scene + +[ 0% ] reimport | Cantarell-VF.otf +[ 4% ] reimport | Cantarell-VF.otf +[ 9% ] reimport | selection.png +[ 13% ] reimport | limestone-albedo.png +[ 18% ] reimport | oak-height-4k.png +[ 22% ] reimport | minimum-window.png +[ 27% ] reimport | menu.png +[ 31% ] reimport | economy.png +[ 36% ] reimport | combat.png +[ 40% ] reimport | build.png +[ 40% ] reimport | build.png +[ 40% ] reimport | build.png +[ 40% ] reimport | build.png +[ 40% ] reimport | build.png +[ 45% ] reimport | unit_w10.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 50% ] reimport | unit_w09.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 54% ] reimport | unit_w08.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 59% ] reimport | unit_w07.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 63% ] reimport | unit_w06.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 68% ] reimport | unit_w05.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 72% ] reimport | unit_w04.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 77% ] reimport | unit_w03.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 81% ] reimport | unit_w02.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 86% ] reimport | unit_w01.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 90% ] reimport | verdant-rift.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 95% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (21 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase10-logs/import2.log b/docs/phase10-logs/import2.log new file mode 100644 index 0000000..08c30cf --- /dev/null +++ b/docs/phase10-logs/import2.log @@ -0,0 +1,260 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] update_scripts_classes | Started Globale Klassen registrieren … (2 steps) +[ 0% ] update_scripts_classes |  +[ 33% ] update_scripts_classes |  +[ DONE ] update_scripts_classes + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (24 steps) +[ 0% ] _update_scan_actions | oak-albedo-4k.png +[ 4% ] _update_scan_actions | core_team0.glb +[ 8% ] _update_scan_actions | core_team1.glb +[ 12% ] _update_scan_actions | enemy_e01.glb +[ 16% ] _update_scan_actions | enemy_e02.glb +[ 20% ] _update_scan_actions | enemy_e03.glb +[ 24% ] _update_scan_actions | enemy_e04.glb +[ 28% ] _update_scan_actions | enemy_e05.glb +[ 32% ] _update_scan_actions | enemy_e06.glb +[ 36% ] _update_scan_actions | enemy_e07.glb +[ 40% ] _update_scan_actions | enemy_e08.glb +[ 44% ] _update_scan_actions | enemy_e09.glb +[ 48% ] _update_scan_actions | enemy_e10.glb +[ 52% ] _update_scan_actions | unit_g01.glb +[ 56% ] _update_scan_actions | unit_g02.glb +[ 60% ] _update_scan_actions | unit_g03.glb +[ 64% ] _update_scan_actions | unit_g04.glb +[ 68% ] _update_scan_actions | unit_g05.glb +[ 72% ] _update_scan_actions | unit_g06.glb +[ 76% ] _update_scan_actions | unit_g07.glb +[ 80% ] _update_scan_actions | unit_g08.glb +[ 84% ] _update_scan_actions | unit_g09.glb +[ 88% ] _update_scan_actions | unit_g10.glb +[ 92% ] _update_scan_actions | worker.glb +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (24 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 4% ] reimport | Dateien zum Neuimport vorbereiten … +[ 8% ] reimport | Dateien zum Neuimport vorbereiten … +[ 12% ] reimport | Dateien zum Neuimport vorbereiten … +[ 16% ] reimport | Dateien zum Neuimport vorbereiten … +[ 20% ] reimport | Dateien zum Neuimport vorbereiten … +[ 24% ] reimport | Dateien zum Neuimport vorbereiten … +[ 28% ] reimport | Dateien zum Neuimport vorbereiten … +[ 32% ] reimport | Dateien zum Neuimport vorbereiten … +[ 36% ] reimport | Dateien zum Neuimport vorbereiten … +[ 40% ] reimport | Dateien zum Neuimport vorbereiten … +[ 44% ] reimport | Dateien zum Neuimport vorbereiten … +[ 48% ] reimport | Dateien zum Neuimport vorbereiten … +[ 52% ] reimport | Dateien zum Neuimport vorbereiten … +[ 56% ] reimport | Dateien zum Neuimport vorbereiten … +[ 60% ] reimport | Dateien zum Neuimport vorbereiten … +[ 64% ] reimport | Dateien zum Neuimport vorbereiten … +[ 68% ] reimport | Dateien zum Neuimport vorbereiten … +[ 72% ] reimport | Dateien zum Neuimport vorbereiten … +[ 76% ] reimport | Dateien zum Neuimport vorbereiten … +[ 80% ] reimport | Dateien zum Neuimport vorbereiten … +[ 84% ] reimport | Dateien zum Neuimport vorbereiten … +[ 88% ] reimport | Dateien zum Neuimport vorbereiten … +[ 92% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] preload_reimporting_scene | Started Szenen zum Neuladen vorbereiten (1 steps) +[ 0% ] preload_reimporting_scene | Szene [leer] wird analysiert +[ 50% ] preload_reimporting_scene | Vorbereitung abgeschlossen. +[ DONE ] preload_reimporting_scene + +[ 0% ] reimport | oak-albedo-4k.png +[ 4% ] reimport | worker.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 8% ] reimport | unit_g10.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 12% ] reimport | unit_g09.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 16% ] reimport | unit_g08.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 20% ] reimport | unit_g07.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 24% ] reimport | unit_g06.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 28% ] reimport | unit_g05.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 32% ] reimport | unit_g04.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 36% ] reimport | unit_g03.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 40% ] reimport | unit_g02.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 44% ] reimport | unit_g01.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 48% ] reimport | enemy_e10.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 52% ] reimport | enemy_e09.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 56% ] reimport | enemy_e08.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 60% ] reimport | enemy_e07.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 64% ] reimport | enemy_e06.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 68% ] reimport | enemy_e05.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 72% ] reimport | enemy_e04.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 76% ] reimport | enemy_e03.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 80% ] reimport | enemy_e02.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 84% ] reimport | enemy_e01.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 88% ] reimport | core_team1.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 92% ] reimport | core_team0.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 96% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (24 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase10-logs/import3.log b/docs/phase10-logs/import3.log new file mode 100644 index 0000000..10ef3b5 --- /dev/null +++ b/docs/phase10-logs/import3.log @@ -0,0 +1,66 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] update_scripts_classes | Started Globale Klassen registrieren … (2 steps) +[ 0% ] update_scripts_classes |  +[ 33% ] update_scripts_classes |  +[ DONE ] update_scripts_classes + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (3 steps) +[ 0% ] _update_scan_actions | limestone-albedo.png +[ 25% ] _update_scan_actions | oak-albedo-4k.png +[ 50% ] _update_scan_actions | oak-height-4k.png +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (3 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 25% ] reimport | Dateien zum Neuimport vorbereiten … +[ 50% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] reimport | limestone-albedo.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 25% ] reimport | oak-albedo-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 50% ] reimport | oak-height-4k.png +[ 75% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (3 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase10-logs/import4.log b/docs/phase10-logs/import4.log new file mode 100644 index 0000000..af11f64 --- /dev/null +++ b/docs/phase10-logs/import4.log @@ -0,0 +1,170 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] update_scripts_classes | Started Globale Klassen registrieren … (5 steps) +[ 0% ] update_scripts_classes |  +[ 16% ] update_scripts_classes |  +[ 33% ] update_scripts_classes |  +[ 50% ] update_scripts_classes |  +[ 66% ] update_scripts_classes |  +[ DONE ] update_scripts_classes + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (13 steps) +[ 0% ] _update_scan_actions | verdant-rift.glb +[ 7% ] _update_scan_actions | oak-albedo-4k.png +[ 14% ] _update_scan_actions | oak-height-4k.png +[ 21% ] _update_scan_actions | unit_w01.glb +[ 28% ] _update_scan_actions | unit_w02.glb +[ 35% ] _update_scan_actions | unit_w03.glb +[ 42% ] _update_scan_actions | unit_w04.glb +[ 50% ] _update_scan_actions | unit_w05.glb +[ 57% ] _update_scan_actions | unit_w06.glb +[ 64% ] _update_scan_actions | unit_w07.glb +[ 71% ] _update_scan_actions | unit_w08.glb +[ 78% ] _update_scan_actions | unit_w09.glb +[ 85% ] _update_scan_actions | unit_w10.glb +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (13 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 7% ] reimport | Dateien zum Neuimport vorbereiten … +[ 14% ] reimport | Dateien zum Neuimport vorbereiten … +[ 21% ] reimport | Dateien zum Neuimport vorbereiten … +[ 28% ] reimport | Dateien zum Neuimport vorbereiten … +[ 35% ] reimport | Dateien zum Neuimport vorbereiten … +[ 42% ] reimport | Dateien zum Neuimport vorbereiten … +[ 50% ] reimport | Dateien zum Neuimport vorbereiten … +[ 57% ] reimport | Dateien zum Neuimport vorbereiten … +[ 64% ] reimport | Dateien zum Neuimport vorbereiten … +[ 71% ] reimport | Dateien zum Neuimport vorbereiten … +[ 78% ] reimport | Dateien zum Neuimport vorbereiten … +[ 85% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] preload_reimporting_scene | Started Szenen zum Neuladen vorbereiten (1 steps) +[ 0% ] preload_reimporting_scene | Szene [leer] wird analysiert +[ 50% ] preload_reimporting_scene | Vorbereitung abgeschlossen. +[ DONE ] preload_reimporting_scene + +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 0% ] reimport | oak-albedo-4k.png +[ 7% ] reimport | oak-height-4k.png +[ 7% ] reimport | oak-height-4k.png +[ 7% ] reimport | oak-height-4k.png +[ 7% ] reimport | oak-height-4k.png +[ 7% ] reimport | oak-height-4k.png +[ 14% ] reimport | verdant-rift.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 21% ] reimport | unit_w01.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 28% ] reimport | unit_w02.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 35% ] reimport | unit_w03.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 42% ] reimport | unit_w04.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 50% ] reimport | unit_w05.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 57% ] reimport | unit_w06.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 64% ] reimport | unit_w07.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 71% ] reimport | unit_w08.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 78% ] reimport | unit_w09.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 85% ] reimport | unit_w10.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 92% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (13 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase10-logs/manifest.log b/docs/phase10-logs/manifest.log new file mode 100644 index 0000000..32d0c51 --- /dev/null +++ b/docs/phase10-logs/manifest.log @@ -0,0 +1,6 @@ +00:00.020 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.020 color_management | Using fallback mode for management +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/model-import.log b/docs/phase10-logs/model-import.log new file mode 100644 index 0000000..49ad186 --- /dev/null +++ b/docs/phase10-logs/model-import.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: Phase 4 models 59/59; 59 entries checked, 0 errors. diff --git a/docs/phase10-logs/package-full-visual.log b/docs/phase10-logs/package-full-visual.log new file mode 100644 index 0000000..6ca7969 --- /dev/null +++ b/docs/phase10-logs/package-full-visual.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1684 checks; 0 failures; /tmp/sw10-package-full/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/package-linux-smoke.log b/docs/phase10-logs/package-linux-smoke.log new file mode 100644 index 0000000..58b7dc8 --- /dev/null +++ b/docs/phase10-logs/package-linux-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw10-package-linux-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase10-logs/package-linux.log b/docs/phase10-logs/package-linux.log new file mode 100644 index 0000000..5550d55 --- /dev/null +++ b/docs/phase10-logs/package-linux.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/sw10-package-linux/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/package-opengl.log b/docs/phase10-logs/package-opengl.log new file mode 100644 index 0000000..8dc6a02 --- /dev/null +++ b/docs/phase10-logs/package-opengl.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /tmp/sw10-package-opengl/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/package-vulkan.log b/docs/phase10-logs/package-vulkan.log new file mode 100644 index 0000000..fd18ca4 --- /dev/null +++ b/docs/phase10-logs/package-vulkan.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /tmp/sw10-package-vulkan/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/package-windows-smoke.log b/docs/phase10-logs/package-windows-smoke.log new file mode 100644 index 0000000..a3e7b1f --- /dev/null +++ b/docs/phase10-logs/package-windows-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw10-package-windows-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase10-logs/package-windows.log b/docs/phase10-logs/package-windows.log new file mode 100644 index 0000000..0f9425b --- /dev/null +++ b/docs/phase10-logs/package-windows.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/sw10-package-windows/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/reference-gallery.log b/docs/phase10-logs/reference-gallery.log new file mode 100644 index 0000000..ae041a3 --- /dev/null +++ b/docs/phase10-logs/reference-gallery.log @@ -0,0 +1 @@ +REFERENCE_GALLERY_PASS: 23 comparison sheets, 46 characters; catalog 59 models diff --git a/docs/phase10-logs/references-glut.log b/docs/phase10-logs/references-glut.log new file mode 100644 index 0000000..22fa02b --- /dev/null +++ b/docs/phase10-logs/references-glut.log @@ -0,0 +1,48 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g01_kohlenbeisser_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g02_schlackenklaue_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-g01.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g03_schlackenwacht_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g04_basaltbastion_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-g03.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g05_funkenlanze_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g06_glasballiste_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-g05.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g07_aschenwerfer_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g08_kraterrufer_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-g07.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g09_herdhueter_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/glutpakt/unit_g10_sonnenesse_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-g09.png diff --git a/docs/phase10-logs/references-root.log b/docs/phase10-logs/references-root.log new file mode 100644 index 0000000..74c9581 --- /dev/null +++ b/docs/phase10-logs/references-root.log @@ -0,0 +1,48 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w01_dornhopser_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w01.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w03_korkruecken_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w04_ringborke_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w03.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w05.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w07.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w09_tauhueter_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w09.png diff --git a/docs/phase10-logs/ringborke-final.log b/docs/phase10-logs/ringborke-final.log new file mode 100644 index 0000000..178a4f2 --- /dev/null +++ b/docs/phase10-logs/ringborke-final.log @@ -0,0 +1,1091 @@ +00:00.015 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.015 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:54:03 | INFO: Starting glTF 2.0 export +20:54:03 | INFO: Extracting primitive: Body_Braid0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Growth5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge6_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge7_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge8_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge9_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge10_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge11_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_RoughEdge12_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Split0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Split1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log0_Split2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Growth5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge6_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge7_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge8_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge9_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge10_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge11_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_RoughEdge12_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Split0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Split1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log1_Split2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Growth5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge6_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge7_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge8_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge9_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge10_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge11_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_RoughEdge12_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Split0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Split1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log2_Split2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Growth5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge6_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge7_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge8_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge9_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge10_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge11_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_RoughEdge12_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Split0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Split1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log3_Split2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Growth5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge3_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge4_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge5_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge6_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge7_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge8_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge9_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge10_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge11_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_RoughEdge12_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Split0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Split1_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log4_Split2_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log5_Bark_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log5_Cut_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log5_Growth0_Mesh +20:54:03 | INFO: Primitives created: 1 +20:54:03 | INFO: Extracting primitive: Body_Log5_Growth1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Growth2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Growth3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Growth4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Growth5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge8_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge9_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge10_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge11_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_RoughEdge12_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Split0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Split1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_Log5_Split2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Moss_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Moss_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:54:04 | INFO: Primitives created: 1 +20:54:04 | INFO: Finished glTF 2.0 export in 0.5525765419006348 s + +EXPORTED w04: 134530 triangles, 539 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb +PHASE4_EXPORT_PASS: 1 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/rules.log b/docs/phase10-logs/rules.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase10-logs/rules.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase10-logs/runtime.log b/docs/phase10-logs/runtime.log new file mode 100644 index 0000000..4374bd8 --- /dev/null +++ b/docs/phase10-logs/runtime.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +PHASE6_RUNTIME: {"audio_events":120,"checks":9,"device":"NVIDIA GeForce RTX 5060 Ti","engine":"4.7.2-stable (fedora)","failures":[],"frames":1726,"max_draw_calls":5064,"mean_fps":143.82613004132,"mean_frame_ms":6.95283951332561,"p95_frame_ms":12.152,"renderer":"forward_plus","sample_seconds":12,"speed":2,"units_at_start":86,"viewport":"(1600.0, 960.0)","wave":20} diff --git a/docs/phase10-logs/sculpt-organic-final.log b/docs/phase10-logs/sculpt-organic-final.log new file mode 100644 index 0000000..020618a --- /dev/null +++ b/docs/phase10-logs/sculpt-organic-final.log @@ -0,0 +1,6919 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:51:56 | INFO: Starting glTF 2.0 export +20:51:56 | INFO: Extracting primitive: Body_Bark0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark0_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark0_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark0_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark0_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark1_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark1_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark1_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark1_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark2_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark2_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark2_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark2_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark3_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark3_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark3_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark3_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark4_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark4_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark4_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark4_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark5_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark5_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark5_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark5_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark5_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark6_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark6_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark6_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark6_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark6_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark7_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark7_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark7_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark7_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark7_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark8_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark8_Fissure0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark8_Fissure1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark8_Fissure2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Bark8_Fissure3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Petal0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Petal1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Petal2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Petal3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Petal4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Blossom_Pollen_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_MossHeart_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn5_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn6_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn7_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_Thorn8_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark0_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark0_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark1_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark1_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark2_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark2_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark3_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark3_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark4_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark4_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark5_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark5_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Body_WovenBark5_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Eye1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_EyeShadow_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout1_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: Head_Sprout_1_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Moss_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Moss_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:56 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:51:56 | INFO: Primitives created: 1 +20:51:57 | INFO: Finished glTF 2.0 export in 0.19468045234680176 s + +EXPORTED w01: 61376 triangles, 166 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb +20:51:58 | INFO: Starting glTF 2.0 export +20:51:58 | INFO: Extracting primitive: Body_Braid0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawDark_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Petal0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Petal1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Petal2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Petal3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Petal4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawFlower_Pollen_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf0_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf1_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf2_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf3_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf4_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_JawLeaf5_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang5_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang6_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang7_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Fang8_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Jaw_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Lip0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Lip1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Lower_Lip2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang5_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang6_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang7_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Fang8_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Jaw_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Lip0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Lip1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: Head_Upper_Lip2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Moss_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Moss_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:51:58 | INFO: Primitives created: 1 +20:51:58 | INFO: Finished glTF 2.0 export in 0.2496647834777832 s + +EXPORTED w02: 78020 triangles, 237 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb +20:52:00 | INFO: Starting glTF 2.0 export +20:52:00 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_0_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_0_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_0_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_0_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_1_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_1_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_1_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_1_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_2_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_2_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_2_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_2_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_3_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_3_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_3_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_3_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_4_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_4_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_4_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_4_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_5_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_5_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_5_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_5_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_5_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_6_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_6_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_6_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_6_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork0_6_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_0_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_0_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_0_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_0_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_1_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_1_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_1_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_1_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_2_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_2_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_2_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_2_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_3_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_3_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_3_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_3_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_4_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_4_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_4_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_4_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_5_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_5_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_5_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_5_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_5_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_6_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_6_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_6_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_6_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork1_6_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_0_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_0_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_0_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_0_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_1_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_1_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_1_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_1_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_2_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_2_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_2_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_2_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_3_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_3_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_3_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_3_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_4_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_4_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_4_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_4_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_5_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_5_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_5_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_5_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_5_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_6_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_6_Fissure0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_6_Fissure1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_6_Fissure2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Cork2_6_Fissure3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:00 | INFO: Primitives created: 1 +20:52:00 | INFO: Finished glTF 2.0 export in 0.3526015281677246 s + +EXPORTED w03: 84786 triangles, 380 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb +20:52:03 | INFO: Starting glTF 2.0 export +20:52:03 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log0_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log1_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log2_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log3_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log4_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Bark_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Cut_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Growth5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge11_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_RoughEdge12_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Split0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Split1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_Log5_Split2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_0_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_1_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_2_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_3_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_4_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_5_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_6_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark0_7_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_0_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_1_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_2_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_3_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_4_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_5_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_6_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark1_7_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_0_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_1_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_2_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_3_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_4_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_5_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_6_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_OverlappingBark2_7_Fissure3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:52:03 | INFO: Primitives created: 1 +20:52:03 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:04 | INFO: Primitives created: 1 +20:52:04 | INFO: Finished glTF 2.0 export in 0.5383317470550537 s + +EXPORTED w04: 134598 triangles, 539 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb +20:52:05 | INFO: Starting glTF 2.0 export +20:52:05 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_Seed_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:05 | INFO: Primitives created: 1 +20:52:05 | INFO: Finished glTF 2.0 export in 0.1848747730255127 s + +EXPORTED w05: 50536 triangles, 204 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb +20:52:06 | INFO: Starting glTF 2.0 export +20:52:06 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_Seed_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:06 | INFO: Primitives created: 1 +20:52:06 | INFO: Finished glTF 2.0 export in 0.2713735103607178 s + +EXPORTED w06: 62588 triangles, 296 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb +20:52:07 | INFO: Starting glTF 2.0 export +20:52:07 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:52:07 | INFO: Primitives created: 1 +20:52:07 | INFO: Finished glTF 2.0 export in 0.3232722282409668 s + +EXPORTED w07: 69164 triangles, 366 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb +20:52:09 | INFO: Starting glTF 2.0 export +20:52:09 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk1_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk1_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk1_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk1_Grain3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk2_Grain0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk2_Grain1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk2_Grain2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_FungalTrunk2_Grain3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Midrib_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1_1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1__1_Mesh +20:52:09 | INFO: Primitives created: 1 +20:52:09 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rib0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rib1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rib2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rib3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rib4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Rim_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup2_Shell_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rib0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rib1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rib2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rib3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rib4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Rim_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_SmallCup3_Shell_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rib11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Rim_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup1_Shell_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib5_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib6_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib7_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib8_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib9_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib10_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rib11_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Rim_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Head_Cup2_Shell_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore1_0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore1_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore1_2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore1_3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore1_4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore2_0_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore2_1_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore2_2_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore2_3_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Extracting primitive: Weapon_Spore2_4_Mesh +20:52:10 | INFO: Primitives created: 1 +20:52:10 | INFO: Finished glTF 2.0 export in 0.6085748672485352 s + +EXPORTED w08: 103748 triangles, 700 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb +20:52:11 | INFO: Starting glTF 2.0 export +20:52:11 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown0_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown1_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown2_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown3_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Head_Crown4_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_DewOrb_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Extracting primitive: Weapon_Water_Mesh +20:52:11 | INFO: Primitives created: 1 +20:52:11 | INFO: Finished glTF 2.0 export in 0.2095043659210205 s + +EXPORTED w09: 52040 triangles, 199 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb +20:52:13 | INFO: Starting glTF 2.0 export +20:52:13 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Moss_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Moss_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Extracting primitive: Weapon_Water_Mesh +20:52:13 | INFO: Primitives created: 1 +20:52:13 | INFO: Finished glTF 2.0 export in 0.31337785720825195 s + +EXPORTED w10: 61052 triangles, 348 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb +PHASE4_EXPORT_PASS: 10 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/sculpt-repair.log b/docs/phase10-logs/sculpt-repair.log new file mode 100644 index 0000000..5605f30 --- /dev/null +++ b/docs/phase10-logs/sculpt-repair.log @@ -0,0 +1,1007 @@ +00:00.015 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.015 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:42:47 | INFO: Starting glTF 2.0 export +20:42:47 | INFO: Extracting primitive: Body_Braid0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_Seed_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Moss_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Moss_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:42:47 | INFO: Primitives created: 1 +20:42:47 | INFO: Finished glTF 2.0 export in 0.2810370922088623 s + +EXPORTED w06: 62588 triangles, 296 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb +20:42:48 | INFO: Starting glTF 2.0 export +20:42:48 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown0_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown1_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown2_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown3_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Head_Crown4_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Moss_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Moss_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_DewOrb_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Extracting primitive: Weapon_Water_Mesh +20:42:48 | INFO: Primitives created: 1 +20:42:48 | INFO: Finished glTF 2.0 export in 0.20449471473693848 s + +EXPORTED w09: 52040 triangles, 199 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb +PHASE4_EXPORT_PASS: 2 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/sculpt-rest.log b/docs/phase10-logs/sculpt-rest.log new file mode 100644 index 0000000..1b5187e --- /dev/null +++ b/docs/phase10-logs/sculpt-rest.log @@ -0,0 +1,5309 @@ +00:00.028 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.028 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:38:47 | INFO: Starting glTF 2.0 export +20:38:47 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_LavaCore_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell0_0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell0_1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell0_2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell0_3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell1_0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell1_1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell1_2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell1_3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell2_0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell2_1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell2_2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Body_Shell2_3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_BrowL_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_BrowR_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_CheekL_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_CheekR_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_Chin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_EyeL_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_EyeR_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_JawCavity_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_MouthEmber_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:47 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +20:38:47 | INFO: Primitives created: 1 +20:38:48 | INFO: Finished glTF 2.0 export in 0.2196025848388672 s + +EXPORTED g01: 79780 triangles, 131 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g01.glb +20:38:49 | INFO: Starting glTF 2.0 export +20:38:49 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_DorsalSpine3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_DorsalSpine4_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_LavaCore_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell0_0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell0_1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell0_2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell0_3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell1_0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell1_1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell1_2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell1_3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell2_0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell2_1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell2_2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Body_Shell2_3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_BrowL_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_BrowR_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_CheekL_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_CheekR_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_Chin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_EyeL_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_EyeR_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_JawCavity_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_MouthEmber_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +20:38:49 | INFO: Primitives created: 1 +20:38:49 | INFO: Finished glTF 2.0 export in 0.19073700904846191 s + +EXPORTED g02: 75624 triangles, 133 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g02.glb +20:38:51 | INFO: Starting glTF 2.0 export +20:38:51 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_BorderL_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_BorderR_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestL_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestR_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_SeamL_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Body_SeamR_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Head_Fire_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:51 | INFO: Primitives created: 1 +20:38:51 | INFO: Finished glTF 2.0 export in 0.18601417541503906 s + +EXPORTED g03: 67232 triangles, 119 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g03.glb +20:38:55 | INFO: Starting glTF 2.0 export +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_BorderL_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_BorderR_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestL_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestR_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_SeamL_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_SeamR_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Body_SpineGold_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_Fire_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:55 | INFO: Primitives created: 1 +20:38:55 | INFO: Finished glTF 2.0 export in 0.2795727252960205 s + +EXPORTED g04: 80764 triangles, 220 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g04.glb +20:38:56 | INFO: Starting glTF 2.0 export +20:38:56 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_ShoulderFin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_ShoulderFin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_ChestStoneL_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_ChestStoneR_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_CuirassL_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_CuirassR_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_EmberHeart_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Body_Spine_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Head_Crest_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Head_Helmet_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Head_Neck_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Head_Visor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ShinEmber_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ShinGold_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ShinEmber_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ShinGold_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar0_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar2_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar3_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar4_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar5_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar6_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar7_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar8_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar9_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceCollar10_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceEmber_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_LanceShaft_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_SpearEdge1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_SpearEdge_1_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Extracting primitive: Weapon_SpearHead_Mesh +20:38:56 | INFO: Primitives created: 1 +20:38:56 | INFO: Finished glTF 2.0 export in 0.15272879600524902 s + +EXPORTED g05: 54710 triangles, 118 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g05.glb +20:38:57 | INFO: Starting glTF 2.0 export +20:38:57 | INFO: Extracting primitive: Body_CrankInsetL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankInsetR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL3_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL4_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL5_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL6_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothL7_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR3_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR4_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR5_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR6_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_CrankToothR7_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Body_Gearbox_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_BoltHead_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_CentralBolt_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_DrawCableL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_DrawCableR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_GlassLimbL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_GlassLimbR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_LimbClampL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_LimbClampR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_LimbEdgeL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_LimbEdgeR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet0_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet1_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet2_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet3_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet4_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailRivet5_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailTrimL_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RailTrimR_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RearHousing_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:57 | INFO: Extracting primitive: Weapon_RearTrim_Mesh +20:38:57 | INFO: Primitives created: 1 +20:38:58 | INFO: Finished glTF 2.0 export in 0.1064004898071289 s + +EXPORTED g06: 38036 triangles, 85 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g06.glb +20:38:59 | INFO: Starting glTF 2.0 export +20:38:59 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: Body_FrontBadge_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: Body_FrontBadgeStone_Mesh +20:38:59 | INFO: Primitives created: 1 +20:38:59 | INFO: Extracting primitive: Body_FrontSigil_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_LowerCore_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarBelt_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarBore_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarLip_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave3_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave4_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave5_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave6_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave7_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave8_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave9_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave10_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_MortarStave11_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp3_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp4_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp5_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp6_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp7_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp8_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp9_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp10_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Body_RimClasp11_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust0_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust1_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust2_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust3_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust4_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust5_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_BoulderCrust6_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_EmberBoulder_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Extracting primitive: Weapon_LavaPool_Mesh +20:39:00 | INFO: Primitives created: 1 +20:39:00 | INFO: Finished glTF 2.0 export in 0.19945812225341797 s + +EXPORTED g07: 81492 triangles, 128 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g07.glb +20:39:01 | INFO: Starting glTF 2.0 export +20:39:01 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_FrontBadge_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_FrontBadgeStone_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_FrontSigil_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_LowerCore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarBelt_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarBore_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarLip_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave0_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave1_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave2_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave3_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave4_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave5_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave6_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave7_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave8_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave9_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave10_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_MortarStave11_Mesh +20:39:01 | INFO: Primitives created: 1 +20:39:01 | INFO: Extracting primitive: Body_RimClasp0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp3_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp4_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp5_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp6_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp7_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp8_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp9_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp10_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Body_RimClasp11_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Weapon_LavaEddy0_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Weapon_LavaEddy1_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Weapon_LavaEddy2_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Extracting primitive: Weapon_LavaPool_Mesh +20:39:02 | INFO: Primitives created: 1 +20:39:02 | INFO: Finished glTF 2.0 export in 0.19971442222595215 s + +EXPORTED g08: 77130 triangles, 123 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g08.glb +20:39:04 | INFO: Starting glTF 2.0 export +20:39:04 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Base_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Face_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Heart_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray3_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray4_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray5_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray6_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray7_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray8_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray9_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray10_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Seal_Ray11_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Base_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Face_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Heart_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray3_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray4_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray5_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray6_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray7_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray8_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray9_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray10_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Seal_Ray11_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone3_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone4_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone5_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone6_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone7_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone8_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone9_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_ArchStone10_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBack_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick0_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick0_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick0_2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick1_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick1_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick1_2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick2_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick2_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_HearthBrick2_2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_OvenDark_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_Pillar1_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_Pillar1_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_Pillar_1_0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Body_Pillar_1_1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Flame_Oven0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Flame_Oven1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Flame_Oven2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Head_Chimney_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Head_ChimneyCap_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Head_ChimneyRecess_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlRim_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Base_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Face_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Heart_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray3_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray4_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray5_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray6_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray7_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray8_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray9_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray10_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_BowlSeal_Ray11_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_EmberBed_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_Flame0_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_Flame1_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_Flame2_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_Flame3_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_Flame4_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Extracting primitive: Weapon_HearthBowl_Mesh +20:39:04 | INFO: Primitives created: 1 +20:39:04 | INFO: Finished glTF 2.0 export in 0.22409749031066895 s + +EXPORTED g09: 84568 triangles, 173 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g09.glb +20:39:08 | INFO: Starting glTF 2.0 export +20:39:08 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Seal_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Seal_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HaloRay8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_HearthBack_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleL_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleR_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunL_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_MantleSunR_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_OvenDark_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_SolarStream_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_SunFrame_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_SunHeart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_SunSocket_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardL_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardR_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunL_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TabardSunR_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Flame_SolarEddy0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Flame_SolarEddy1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Flame_SolarEddy2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlRim_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Base_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Face_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Heart_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray8_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray9_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray10_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_BowlSeal_Ray11_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_EmberBed_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_Flame0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_Flame1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_Flame2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_Flame3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_Flame4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Weapon_HearthBowl_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Finished glTF 2.0 export in 0.2618117332458496 s + +EXPORTED g10: 96706 triangles, 223 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_g10.glb +20:39:08 | INFO: Starting glTF 2.0 export +20:39:08 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Finger2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Forearm_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Finger2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Forearm_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ApronRivet6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ClayTorso_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_Harness1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_Harness_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_LeatherApron_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_Reservoir_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace0_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace2_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace3_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace4_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace5_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace6_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankBrace7_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankRim0_45_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_TankRim0_79_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Body_ToolPocket_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_Cap_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_FaceRecess_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_GoggleGlint1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_GoggleGlint_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_GoggleLens1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:08 | INFO: Extracting primitive: Head_GoggleLens_1_Mesh +20:39:08 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Head_GoggleSocket1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Head_GoggleSocket_1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Head_Hood_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Head_Lamp_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Head_LampHousing_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_Boot_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_Cuff_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_Shin_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_Sole_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_ToeRidge0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_ToeRidge1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegL_ToeRidge2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_Boot_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_Cuff_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_Shin_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_Sole_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_ToeRidge0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_ToeRidge1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: LegR_ToeRidge2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: WeaponL_Fork_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: WeaponL_Handle_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: WeaponR_Probe_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Finished glTF 2.0 export in 0.09981608390808105 s + +EXPORTED worker: 24026 triangles, 65 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/worker.glb +20:39:09 | INFO: Starting glTF 2.0 export +20:39:09 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal5_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal6_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal7_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal8_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal9_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal10_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Body_Seal11_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Extracting primitive: Team_Circle_Mesh +20:39:09 | INFO: Primitives created: 1 +20:39:09 | INFO: Finished glTF 2.0 export in 0.09598422050476074 s + +EXPORTED core_team0: 36652 triangles, 64 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team0.glb +20:39:10 | INFO: Starting glTF 2.0 export +20:39:10 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal5_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal6_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal7_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal8_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal9_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal10_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Seal11_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Team_Triangle0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Team_Triangle1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Team_Triangle2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Finished glTF 2.0 export in 0.09809088706970215 s + +EXPORTED core_team1: 36848 triangles, 66 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team1.glb +20:39:10 | INFO: Starting glTF 2.0 export +20:39:10 | INFO: Extracting primitive: Body_Carapace0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Carapace1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Carapace2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Carapace3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_Core_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_SeamGlow0_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_SeamGlow1_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_SeamGlow2_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Body_SeamGlow3_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Head_EyeL_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Head_EyeR_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Head_MandibleL_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Head_MandibleR_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: Head_Skull_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL0_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL0_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL0_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL0_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL1_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL1_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL1_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL1_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL2_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL2_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL2_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegL2_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR0_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR0_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR0_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR0_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR1_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR1_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR1_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR1_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR2_Inset_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR2_Joint_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR2_Shin_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Extracting primitive: LegR2_Upper_Mesh +20:39:10 | INFO: Primitives created: 1 +20:39:10 | INFO: Finished glTF 2.0 export in 0.05674314498901367 s + +EXPORTED e01: 19228 triangles, 38 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e01.glb +20:39:11 | INFO: Starting glTF 2.0 export +20:39:11 | INFO: Extracting primitive: Body_Carapace0_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Carapace1_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Carapace2_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Carapace3_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Core_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_SeamGlow0_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_SeamGlow1_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_SeamGlow2_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_SeamGlow3_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Spine0_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Spine1_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Spine2_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Body_Spine3_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Head_EyeL_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Head_EyeR_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Head_MandibleL_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Head_MandibleR_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: Head_Skull_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL0_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL0_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL0_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL0_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL1_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL1_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL1_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL1_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL2_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL2_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL2_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegL2_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR0_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR0_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR0_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR0_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR1_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR1_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR1_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR1_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR2_Inset_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR2_Joint_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR2_Shin_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Extracting primitive: LegR2_Upper_Mesh +20:39:11 | INFO: Primitives created: 1 +20:39:11 | INFO: Finished glTF 2.0 export in 0.08610177040100098 s + +EXPORTED e02: 20180 triangles, 42 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e02.glb +20:39:12 | INFO: Starting glTF 2.0 export +20:39:12 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibL0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibL1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibL2_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibL3_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibL4_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibR0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibR1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibR2_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibR3_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RibR4_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_RiftHalo_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud0_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud1_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud2_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud3_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud4_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud5_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Shroud6_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Body_Torso_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Head_EyeL_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Head_EyeR_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Head_Face_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Extracting primitive: Head_Skull_Mesh +20:39:12 | INFO: Primitives created: 1 +20:39:12 | INFO: Finished glTF 2.0 export in 0.0950930118560791 s + +EXPORTED e03: 35898 triangles, 69 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e03.glb +20:39:13 | INFO: Starting glTF 2.0 export +20:39:13 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibL0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibL1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibL2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibL3_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibL4_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibR0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibR1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibR2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibR3_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_RibR4_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Body_Torso_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Head_EyeL_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Head_EyeR_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Head_Face_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Head_Skull_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ShinEmber_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ShinGold_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ShinEmber_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ShinGold_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Weapon_Arrow_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Weapon_Bow1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Weapon_Bow_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Weapon_String1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Extracting primitive: Weapon_String_1_Mesh +20:39:13 | INFO: Primitives created: 1 +20:39:13 | INFO: Finished glTF 2.0 export in 0.1464238166809082 s + +EXPORTED e04: 51050 triangles, 110 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e04.glb +20:39:15 | INFO: Starting glTF 2.0 export +20:39:15 | INFO: Extracting primitive: ArmL_Cuff_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Knuckle0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Knuckle1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Knuckle2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_StoneHammer_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Cuff_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Knuckle0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Knuckle1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Knuckle2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_StoneHammer_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_BackSlab0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_BackSlab1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_BackSlab2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_BackSlab3_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_BruteCore_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest0_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest0__1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest1_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest1__1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest2_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_Chest2__1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_RiftCrack_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeL0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeL1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeL2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeR0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeR1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Body_ShoulderSpikeR2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_EyeLight1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_EyeLight_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_EyeSocket1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_EyeSocket_1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_MouthSlit0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_MouthSlit1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_MouthSlit2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_Nose_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: Head_Mask_Porcelain_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:15 | INFO: Primitives created: 1 +20:39:15 | INFO: Finished glTF 2.0 export in 0.16916155815124512 s + +EXPORTED e05: 62798 triangles, 125 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e05.glb +20:39:16 | INFO: Starting glTF 2.0 export +20:39:16 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_HealingKnot0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_HealingKnot1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_HealingKnot2_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_KnotRing0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_KnotRing1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_KnotRing2_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_KnotRing3_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeCore_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold2_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold3_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold4_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold5_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold6_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold7_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Body_RobeFold8_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_EyeLight1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_EyeLight_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_EyeSocket1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_EyeSocket_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_MouthSlit0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_MouthSlit1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_MouthSlit2_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_Nose_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Head_Face_Porcelain_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_KnotBranch1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_KnotBranch_1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_Staff_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffCollar0_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffCollar1_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffCollar2_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffCollar3_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffCollar4_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffHeart_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Extracting primitive: Weapon_StaffKnot_Mesh +20:39:16 | INFO: Primitives created: 1 +20:39:16 | INFO: Finished glTF 2.0 export in 0.11782574653625488 s + +EXPORTED e06: 48336 triangles, 84 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e06.glb +20:39:17 | INFO: Starting glTF 2.0 export +20:39:17 | INFO: Extracting primitive: Body_BackArmor0_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_BackArmor1_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_BackArmor2_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_BackArmor3_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_BackArmor4_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_DeerCore_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibL0_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibL1_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibL2_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibL3_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibR0_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibR1_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibR2_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_RibR3_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Body_Tail_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerL_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngL0_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngL1_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngL2_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngR0_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngR1_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerProngR2_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_AntlerR_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_EyeL_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_EyeR_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_Muzzle_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_Neck_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_Nose_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: Head_Skull_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL0_ClovenLine_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL0_Hoof_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL0_Knee_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL0_Shin_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL0_Upper_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL1_ClovenLine_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL1_Hoof_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL1_Knee_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL1_Shin_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegL1_Upper_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR0_ClovenLine_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR0_Hoof_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR0_Knee_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR0_Shin_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR0_Upper_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR1_ClovenLine_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR1_Hoof_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR1_Knee_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR1_Shin_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Extracting primitive: LegR1_Upper_Mesh +20:39:17 | INFO: Primitives created: 1 +20:39:17 | INFO: Finished glTF 2.0 export in 0.07541346549987793 s + +EXPORTED e07: 33800 triangles, 49 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e07.glb +20:39:20 | INFO: Starting glTF 2.0 export +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_BorderL_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_BorderR_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestL_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestR_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RiftHorn1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_RiftHorn_1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_SeamL_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_SeamR_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Body_SpineGold_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_Fire_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:39:20 | INFO: Primitives created: 1 +20:39:20 | INFO: Finished glTF 2.0 export in 0.28160905838012695 s + +EXPORTED e08: 81240 triangles, 222 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e08.glb +20:39:22 | INFO: Starting glTF 2.0 export +20:39:22 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_Chains1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_Chains_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask0_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask1_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask2_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask3_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CourtMask4_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CrownSpike0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CrownSpike1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CrownSpike2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CrownSpike3_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_CrownSpike4_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_JudgeGlow_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_JudgeHalo_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_KnotRing0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_KnotRing1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_KnotRing2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_KnotRing3_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeCore_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold3_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold4_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold5_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold6_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold7_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Body_RobeFold8_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_EyeLight1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_EyeLight_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_EyeSocket1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_EyeSocket_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_MouthSlit0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_MouthSlit1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_MouthSlit2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_Nose_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Head_Face_Porcelain_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_KnotBranch1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_KnotBranch_1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_Staff_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffCollar0_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffCollar1_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffCollar2_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffCollar3_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffCollar4_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffHeart_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Extracting primitive: Weapon_StaffKnot_Mesh +20:39:22 | INFO: Primitives created: 1 +20:39:22 | INFO: Finished glTF 2.0 export in 0.17588186264038086 s + +EXPORTED e09: 57310 triangles, 135 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e09.glb +20:39:23 | INFO: Starting glTF 2.0 export +20:39:23 | INFO: Extracting primitive: Body_CrownCore_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeL0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeL1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeL2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeL3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeR0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeR1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeR2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_RidgeR3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellL0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellL1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellL2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellL3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellR0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellR1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellR2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_ShellR3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Body_Tail_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Brow1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Brow_1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownBand_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem4_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem5_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownGem6_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint4_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint5_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_CrownPoint6_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Eye1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_MawRim_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_MawVoid_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_RiftThroat_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth3_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth4_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth5_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth6_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth7_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth8_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth9_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth10_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth11_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth12_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: Head_Tooth13_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Claw0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Claw1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Claw2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Inner_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Joint_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Shin_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL0_Thigh_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Claw0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Claw1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Claw2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Inner_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Joint_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Shin_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegL1_Thigh_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Claw0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Claw1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Claw2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Inner_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Joint_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Shin_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR0_Thigh_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Claw0_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Claw1_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Claw2_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Inner_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Joint_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Shin_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Extracting primitive: LegR1_Thigh_Mesh +20:39:23 | INFO: Primitives created: 1 +20:39:23 | INFO: Finished glTF 2.0 export in 0.13557648658752441 s + +EXPORTED e10: 64694 triangles, 82 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e10.glb +SCULPT_BATCH_PASS +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/sculpt-stats.log b/docs/phase10-logs/sculpt-stats.log new file mode 100644 index 0000000..719bca6 --- /dev/null +++ b/docs/phase10-logs/sculpt-stats.log @@ -0,0 +1,7 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +SCULPT_SOURCE_STATS_PASS +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/sculpt-wurzelbund-final.log b/docs/phase10-logs/sculpt-wurzelbund-final.log new file mode 100644 index 0000000..cb9029d --- /dev/null +++ b/docs/phase10-logs/sculpt-wurzelbund-final.log @@ -0,0 +1,6595 @@ +00:00.015 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.015 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:45:17 | INFO: Starting glTF 2.0 export +20:45:17 | INFO: Extracting primitive: Body_Bark0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark0_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark0_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark0_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark0_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark1_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark1_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark1_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark1_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark2_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark2_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark2_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark2_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark3_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark3_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark3_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark3_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark4_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark4_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark4_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark4_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark5_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark5_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark5_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark5_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark5_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark6_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark6_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark6_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark6_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark6_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark7_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark7_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark7_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark7_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark7_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark8_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark8_Fissure0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark8_Fissure1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark8_Fissure2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Bark8_Fissure3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Petal0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Petal1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Petal2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Petal3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Petal4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Blossom_Pollen_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_MossHeart_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn5_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn6_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn7_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_Thorn8_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark0_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark0_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark1_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark1_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark2_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark2_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark3_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark3_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark4_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark4_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark5_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark5_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Body_WovenBark5_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Eye1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_EyeShadow_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout1_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: Head_Sprout_1_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:17 | INFO: Primitives created: 1 +20:45:17 | INFO: Finished glTF 2.0 export in 0.2084953784942627 s + +EXPORTED w01: 61376 triangles, 166 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb +20:45:18 | INFO: Starting glTF 2.0 export +20:45:18 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid4_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawDark_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Petal0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Petal1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Petal2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Petal3_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Petal4_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawFlower_Pollen_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf0_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf1_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf2_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf3_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf4_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Midrib_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein0_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein0__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein1_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein1__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein2_1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_JawLeaf5_Vein2__1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang0_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang1_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang2_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang3_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang4_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang5_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang6_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang7_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Fang8_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Jaw_Mesh +20:45:18 | INFO: Primitives created: 1 +20:45:18 | INFO: Extracting primitive: Head_Lower_Lip0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Lower_Lip1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Lower_Lip2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang3_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang4_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang5_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang6_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang7_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Fang8_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Jaw_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Lip0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Lip1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: Head_Upper_Lip2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:19 | INFO: Primitives created: 1 +20:45:19 | INFO: Finished glTF 2.0 export in 0.26677942276000977 s + +EXPORTED w02: 78020 triangles, 237 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb +20:45:21 | INFO: Starting glTF 2.0 export +20:45:21 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_0_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_0_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_0_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_0_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_1_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_1_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_1_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_1_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_2_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_2_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_2_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_2_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_3_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_3_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_3_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_3_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_4_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_4_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_4_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_4_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_5_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_5_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_5_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_5_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_5_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_6_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_6_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_6_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_6_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork0_6_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_0_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_0_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_0_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_0_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_1_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_1_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_1_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_1_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_2_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_2_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_2_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_2_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_3_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_3_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_3_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_3_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_4_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_4_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_4_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_4_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_5_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_5_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_5_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_5_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_5_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_6_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_6_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_6_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_6_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork1_6_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_0_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_0_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_0_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_0_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_1_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_1_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_1_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_1_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_2_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_2_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_2_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_2_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_3_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_3_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_3_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_3_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_4_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_4_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_4_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_4_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_5_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_5_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_5_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_5_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_5_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_6_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_6_Fissure0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_6_Fissure1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_6_Fissure2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Cork2_6_Fissure3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:21 | INFO: Primitives created: 1 +20:45:21 | INFO: Finished glTF 2.0 export in 0.37865424156188965 s + +EXPORTED w03: 84786 triangles, 380 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb +20:45:24 | INFO: Starting glTF 2.0 export +20:45:24 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log0_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log1_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log2_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log3_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log4_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Bark_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Cut_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Growth0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Growth1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Growth2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Growth3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_Growth4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_Log5_RoughEdge9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:24 | INFO: Primitives created: 1 +20:45:24 | INFO: Finished glTF 2.0 export in 0.41384363174438477 s + +EXPORTED w04: 100360 triangles, 377 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb +20:45:25 | INFO: Starting glTF 2.0 export +20:45:25 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_Seed_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:25 | INFO: Primitives created: 1 +20:45:25 | INFO: Finished glTF 2.0 export in 0.22399115562438965 s + +EXPORTED w05: 50536 triangles, 204 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb +20:45:26 | INFO: Starting glTF 2.0 export +20:45:26 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_Seed_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:26 | INFO: Primitives created: 1 +20:45:26 | INFO: Finished glTF 2.0 export in 0.29000401496887207 s + +EXPORTED w06: 62588 triangles, 296 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb +20:45:28 | INFO: Starting glTF 2.0 export +20:45:28 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:45:28 | INFO: Primitives created: 1 +20:45:28 | INFO: Finished glTF 2.0 export in 0.3576076030731201 s + +EXPORTED w07: 69164 triangles, 366 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb +20:45:30 | INFO: Starting glTF 2.0 export +20:45:30 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk1_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk1_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk1_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk1_Grain3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk2_Grain0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk2_Grain1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk2_Grain2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_FungalTrunk2_Grain3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rib0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rib1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rib2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rib3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rib4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Rim_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup2_Shell_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rib0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rib1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rib2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rib3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rib4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Rim_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_SmallCup3_Shell_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2__1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe5_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe5_Midrib_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0_1_Mesh +20:45:30 | INFO: Primitives created: 1 +20:45:30 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib5_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib6_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib7_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib8_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib9_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib10_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rib11_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Rim_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup1_Shell_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib5_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib6_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib7_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib8_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib9_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib10_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rib11_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Rim_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Head_Cup2_Shell_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore1_0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore1_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore1_2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore1_3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore1_4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore2_0_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore2_1_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore2_2_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore2_3_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Extracting primitive: Weapon_Spore2_4_Mesh +20:45:31 | INFO: Primitives created: 1 +20:45:31 | INFO: Finished glTF 2.0 export in 0.6493539810180664 s + +EXPORTED w08: 103748 triangles, 700 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb +20:45:32 | INFO: Starting glTF 2.0 export +20:45:32 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown0_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown1_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown2_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown3_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Head_Crown4_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_DewOrb_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Extracting primitive: Weapon_Water_Mesh +20:45:32 | INFO: Primitives created: 1 +20:45:32 | INFO: Finished glTF 2.0 export in 0.24538922309875488 s + +EXPORTED w09: 52040 triangles, 199 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb +20:45:34 | INFO: Starting glTF 2.0 export +20:45:34 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Moss_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Moss_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Extracting primitive: Weapon_Water_Mesh +20:45:34 | INFO: Primitives created: 1 +20:45:34 | INFO: Finished glTF 2.0 export in 0.3487107753753662 s + +EXPORTED w10: 61052 triangles, 348 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb +PHASE4_EXPORT_PASS: 10 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/sculpt-wurzelbund.log b/docs/phase10-logs/sculpt-wurzelbund.log new file mode 100644 index 0000000..a069d7d --- /dev/null +++ b/docs/phase10-logs/sculpt-wurzelbund.log @@ -0,0 +1,6595 @@ +00:00.020 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.020 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:35:34 | INFO: Starting glTF 2.0 export +20:35:34 | INFO: Extracting primitive: Body_Bark0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark0_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark0_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark0_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark0_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark1_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark1_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark1_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark1_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark2_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark2_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark2_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark2_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark3_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark3_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark3_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark3_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark4_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark4_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark4_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark4_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark5_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark5_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark5_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark5_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark5_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark6_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark6_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark6_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark6_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark6_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark7_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark7_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark7_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark7_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark7_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark8_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark8_Fissure0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark8_Fissure1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark8_Fissure2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Bark8_Fissure3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Petal0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Petal1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Petal2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Petal3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Petal4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Blossom_Pollen_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_MossHeart_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn5_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn6_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn7_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_Thorn8_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark0_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark0_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark1_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark1_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark2_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark2_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark3_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark3_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark4_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark4_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark5_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark5_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Body_WovenBark5_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Eye1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_EyeShadow_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout1_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: Head_Sprout_1_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:34 | INFO: Primitives created: 1 +20:35:34 | INFO: Finished glTF 2.0 export in 0.20621538162231445 s + +EXPORTED w01: 61376 triangles, 166 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb +20:35:35 | INFO: Starting glTF 2.0 export +20:35:35 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawDark_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Petal0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Petal1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Petal2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Petal3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Petal4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawFlower_Pollen_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf0_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf1_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf2_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf3_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf4_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_JawLeaf5_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang5_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang6_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang7_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Fang8_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Jaw_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Lip0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Lip1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Lower_Lip2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang5_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang6_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang7_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Fang8_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Jaw_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Lip0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Lip1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: Head_Upper_Lip2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:35 | INFO: Primitives created: 1 +20:35:35 | INFO: Finished glTF 2.0 export in 0.24980878829956055 s + +EXPORTED w02: 78020 triangles, 237 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb +20:35:37 | INFO: Starting glTF 2.0 export +20:35:37 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_0_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_0_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_0_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_0_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_1_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_1_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_1_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_1_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_2_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_2_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_2_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_2_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_3_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_3_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_3_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_3_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_4_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_4_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_4_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_4_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_5_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_5_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_5_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_5_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_5_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_6_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_6_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_6_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_6_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork0_6_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_0_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_0_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_0_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_0_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_1_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_1_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_1_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_1_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_2_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_2_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_2_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_2_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_3_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_3_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_3_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_3_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_4_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_4_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_4_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_4_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_5_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_5_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_5_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_5_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_5_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_6_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_6_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_6_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_6_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork1_6_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_0_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_0_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_0_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_0_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_1_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_1_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_1_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_1_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_2_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_2_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_2_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_2_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_3_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_3_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_3_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_3_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_4_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_4_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_4_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_4_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_5_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_5_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_5_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_5_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_5_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_6_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_6_Fissure0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_6_Fissure1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_6_Fissure2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Cork2_6_Fissure3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:37 | INFO: Primitives created: 1 +20:35:37 | INFO: Finished glTF 2.0 export in 0.34481215476989746 s + +EXPORTED w03: 84786 triangles, 380 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb +20:35:39 | INFO: Starting glTF 2.0 export +20:35:39 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log0_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log1_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log2_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log3_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log4_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Bark_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Cut_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Growth0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Growth1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Growth2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Growth3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_Growth4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge8_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_Log5_RoughEdge9_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:39 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:35:39 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:40 | INFO: Primitives created: 1 +20:35:40 | INFO: Finished glTF 2.0 export in 0.37867188453674316 s + +EXPORTED w04: 100360 triangles, 377 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb +20:35:41 | INFO: Starting glTF 2.0 export +20:35:41 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_Seed_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:41 | INFO: Primitives created: 1 +20:35:41 | INFO: Finished glTF 2.0 export in 0.21352767944335938 s + +EXPORTED w05: 53696 triangles, 204 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb +20:35:42 | INFO: Starting glTF 2.0 export +20:35:42 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_Seed_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:42 | INFO: Primitives created: 1 +20:35:42 | INFO: Finished glTF 2.0 export in 0.2799491882324219 s + +EXPORTED w06: 62552 triangles, 296 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb +20:35:43 | INFO: Starting glTF 2.0 export +20:35:43 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:35:43 | INFO: Primitives created: 1 +20:35:43 | INFO: Finished glTF 2.0 export in 0.32741737365722656 s + +EXPORTED w07: 69164 triangles, 366 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb +20:35:45 | INFO: Starting glTF 2.0 export +20:35:45 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:45 | INFO: Primitives created: 1 +20:35:45 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk1_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk1_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk1_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk1_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk2_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk2_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk2_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_FungalTrunk2_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup2_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_SmallCup3_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rib11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup1_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib5_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib6_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib7_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib8_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib9_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib10_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rib11_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Rim_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Head_Cup2_Shell_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore1_0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore1_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore1_2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore1_3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore1_4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore2_0_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore2_1_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore2_2_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore2_3_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Extracting primitive: Weapon_Spore2_4_Mesh +20:35:46 | INFO: Primitives created: 1 +20:35:46 | INFO: Finished glTF 2.0 export in 0.6275529861450195 s + +EXPORTED w08: 103748 triangles, 700 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb +20:35:47 | INFO: Starting glTF 2.0 export +20:35:47 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown0_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown1_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown2_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown3_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Head_Crown4_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_DewOrb_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Extracting primitive: Weapon_Water_Mesh +20:35:47 | INFO: Primitives created: 1 +20:35:47 | INFO: Finished glTF 2.0 export in 0.19178295135498047 s + +EXPORTED w09: 57000 triangles, 199 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb +20:35:49 | INFO: Starting glTF 2.0 export +20:35:49 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Moss_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Moss_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Extracting primitive: Weapon_Water_Mesh +20:35:49 | INFO: Primitives created: 1 +20:35:49 | INFO: Finished glTF 2.0 export in 0.34414052963256836 s + +EXPORTED w10: 64028 triangles, 348 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb +PHASE4_EXPORT_PASS: 10 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/smoke.log b/docs/phase10-logs/smoke.log new file mode 100644 index 0000000..e33ec7f --- /dev/null +++ b/docs/phase10-logs/smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw10-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase10-logs/source-pbr.log b/docs/phase10-logs/source-pbr.log new file mode 100644 index 0000000..fa5aaf2 --- /dev/null +++ b/docs/phase10-logs/source-pbr.log @@ -0,0 +1,7 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +BLENDER_PBR_SOURCE_PASS: 33 independent scenes with editable high-resolution geometry and material nodes. +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/standalone-build.log b/docs/phase10-logs/standalone-build.log new file mode 100644 index 0000000..4d83bbc --- /dev/null +++ b/docs/phase10-logs/standalone-build.log @@ -0,0 +1,9 @@ +create_melee.py · 8 Varianten +create_tank.py · 8 Varianten +create_ranged.py · 8 Varianten +create_artillery.py · 8 Varianten +create_support.py · 8 Varianten +create_mercenary.py · 5 Varianten +create_worker.py · 1 Varianten +create_lane.py · 1 Varianten +create_core.py · 2 Varianten diff --git a/docs/phase10-logs/standalone-final.log b/docs/phase10-logs/standalone-final.log new file mode 100644 index 0000000..8bb50e0 --- /dev/null +++ b/docs/phase10-logs/standalone-final.log @@ -0,0 +1,2938 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +/tmp/saumwacht-standalone-odcjpne_/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:56:25 | INFO: Starting glTF 2.0 export +20:56:25 | INFO: Extracting primitive: ArmL0_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL0_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL0_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL0_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL1_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL1_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL1_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL1_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL2_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL2_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL2_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL2_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmL_Shoulder_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR0_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR0_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR0_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR0_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR1_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR1_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR1_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR1_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR2_Housing_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR2_Pivot_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR2_Pivot_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR2_Rod_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: ArmR_Shoulder_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Body_Breastplate_Face_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Body_Breastplate_Rim_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Body_HipPlateL_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Body_HipPlateR_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Body_Waist_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Head_Eye1_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Head_Face_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_AnkleGold_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Greave_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Knee_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Knee_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Piston_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Shin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_ThighArmor_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Toe0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg0_Toe1_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_AnkleGold_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Greave_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Knee_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Knee_Pin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Piston_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Shin_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_ThighArmor_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Toe0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: Leg1_Toe1_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponL0_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponL1_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponL2_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponR0_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponR1_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Extracting primitive: WeaponR2_Blade0_Mesh +20:56:25 | INFO: Primitives created: 1 +20:56:25 | INFO: Finished glTF 2.0 export in 0.06129956245422363 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_tank.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_tank.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED m04: 1398 triangles, 60 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_m04.glb +STANDALONE_PASS: m04 +20:56:29 | INFO: Starting glTF 2.0 export +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_BorderL_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_BorderR_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestL_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestR_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_SeamL_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_SeamR_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Body_SpineGold_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_Fire_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:56:29 | INFO: Primitives created: 1 +20:56:29 | INFO: Finished glTF 2.0 export in 0.2876570224761963 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_ranged.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_ranged.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED g04: 80764 triangles, 220 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_g04.glb +STANDALONE_PASS: g04 +20:56:30 | INFO: Starting glTF 2.0 export +20:56:30 | INFO: Extracting primitive: Body_Braid0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_Seed_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Moss_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Moss_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:30 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:56:30 | INFO: Primitives created: 1 +20:56:31 | INFO: Finished glTF 2.0 export in 0.28821277618408203 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_artillery.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w06: 62588 triangles, 296 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_w06.glb +STANDALONE_PASS: w06 +20:56:31 | INFO: Starting glTF 2.0 export +20:56:31 | INFO: Extracting primitive: ArmL_Sickle_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: ArmR_Sickle_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_ArchMask_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_ArchMask_Eye1_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_ArchMask_Eye_1_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_BellSkirt_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_CathedralFrontArch_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_CathedralShell_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_CentralFlow_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_TailL_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_TailR_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_WispL_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Body_WispR_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Head_CentralSpire_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Head_SpireL_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Head_SpireR_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Weapon_Clapper_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Extracting primitive: Weapon_ClapperChain_Mesh +20:56:31 | INFO: Primitives created: 1 +20:56:31 | INFO: Finished glTF 2.0 export in 0.020352602005004883 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_support.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_support.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED n08: 1482 triangles, 18 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_n08.glb +STANDALONE_PASS: n08 +20:56:32 | INFO: Starting glTF 2.0 export +20:56:32 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Moss_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Moss_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Extracting primitive: Weapon_Water_Mesh +20:56:32 | INFO: Primitives created: 1 +20:56:32 | INFO: Finished glTF 2.0 export in 0.33802247047424316 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_mercenary.py:234: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w10: 61052 triangles, 348 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_w10.glb +STANDALONE_PASS: w10 +20:56:33 | INFO: Starting glTF 2.0 export +20:56:33 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmL_Lower_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmL_PauldronCap_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmR_Lower_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmR_PauldronCap_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Body_Armor_Face_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Body_Armor_Rim_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Body_Belt_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Body_Tabard_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_Crest_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_Eye1_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_HelmetBack_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_Visor_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Head_VisorSlit_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegL_Boot_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegL_KneePlate_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegL_Shin_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegL_Strap_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegL_Thigh_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegR_Boot_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegR_KneePlate_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegR_Shin_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegR_Strap_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: LegR_Thigh_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Weapon_Haft_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Weapon_Head_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Weapon_TriangleInset_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Weapon_TriangleRim_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Extracting primitive: Weapon_Wedge_Mesh +20:56:33 | INFO: Primitives created: 1 +20:56:33 | INFO: Finished glTF 2.0 export in 0.04321742057800293 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_worker.py:190: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_worker.py:460: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED s04: 10458 triangles, 35 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_s04.glb +STANDALONE_PASS: s04 +20:56:34 | INFO: Starting glTF 2.0 export +20:56:34 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Finger0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Finger1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Finger2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Forearm_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Finger0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Finger1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Finger2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Forearm_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet4_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet5_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ApronRivet6_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ClayTorso_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_Harness1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_Harness_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LeatherApron_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_Reservoir_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace4_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace5_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace6_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankBrace7_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankRim0_45_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_TankRim0_79_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_ToolPocket_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_Cap_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_FaceRecess_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleGlint1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleGlint_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleLens1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleLens_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleSocket1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_GoggleSocket_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_Hood_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_Lamp_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Head_LampHousing_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_Boot_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_Cuff_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_Shin_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_Sole_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_ToeRidge0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_ToeRidge1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegL_ToeRidge2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_Boot_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_Cuff_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_Shin_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_Sole_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_ToeRidge0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_ToeRidge1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: LegR_ToeRidge2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: WeaponL_Fork_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: WeaponL_Handle_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: WeaponR_Probe_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Finished glTF 2.0 export in 0.08282303810119629 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_lane.py:189: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_lane.py:459: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED worker: 24026 triangles, 65 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/worker.glb +STANDALONE_PASS: worker +20:56:34 | INFO: Starting glTF 2.0 export +20:56:34 | INFO: Extracting primitive: Body_EdgeCap1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap1_2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap1_3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap_1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap_1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap_1_2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeCap_1_3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone1_2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone1_3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone_1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone_1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone_1_2_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_EdgeStone_1_3_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneFoundation_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_00_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_01_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_02_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_03_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_04_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LaneSlab_05_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LBasalt_00_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LBasalt_01_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LBasalt_02_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LBrassMarker_00_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LBrassMarker_01_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightGlass1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightGlass1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightGlass_1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightGlass_1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightRecess1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightRecess1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightRecess_1_0_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LightRecess_1_1_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LMoss_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_LRetainingLip_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RBasalt_00_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RBasalt_01_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RBasalt_02_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RBrassMarker_00_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RBrassMarker_01_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RMoss_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Extracting primitive: Body_RRetainingLip_Mesh +20:56:34 | INFO: Primitives created: 1 +20:56:34 | INFO: Finished glTF 2.0 export in 0.07767796516418457 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_core.py:203: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_core.py:473: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_core.py:1396: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + +EXPORTED map_lane_segment: 10700 triangles, 45 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/map_lane_segment.glb +STANDALONE_PASS: map_lane_segment +20:56:35 | INFO: Starting glTF 2.0 export +20:56:35 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal5_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal6_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal7_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal8_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal9_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal10_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Body_Seal11_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Team_Triangle0_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Team_Triangle1_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Extracting primitive: Team_Triangle2_Mesh +20:56:35 | INFO: Primitives created: 1 +20:56:35 | INFO: Finished glTF 2.0 export in 0.09733033180236816 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED core_team1: 36848 triangles, 66 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/core_team1.glb +STANDALONE_PASS: core_team1 +STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved +20:56:37 | INFO: Starting glTF 2.0 export +20:56:37 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_LavaCore_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell0_0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell0_1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell0_2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell0_3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell1_0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell1_1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell1_2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell1_3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell2_0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell2_1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell2_2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Body_Shell2_3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_BrowL_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_BrowR_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_CheekL_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_CheekR_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_Chin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_EyeL_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_EyeR_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_JawCavity_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_MouthEmber_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +20:56:37 | INFO: Primitives created: 1 +20:56:37 | INFO: Finished glTF 2.0 export in 0.2093501091003418 s +/tmp/saumwacht-standalone-odcjpne_/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-odcjpne_/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED g01: 79780 triangles, 131 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_g01.glb +STANDALONE_PASS: g01 +20:56:39 | INFO: Starting glTF 2.0 export +20:56:39 | INFO: Extracting primitive: ArmL_Elbow_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Palm_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_Shoulder_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_UpperBand_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_UpperCore_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_WristBand_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Elbow_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Palm_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_Shoulder_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_UpperBand_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_UpperCore_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_WristBand_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_LavaCore_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell0_0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell0_1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell0_2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell0_3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell1_0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell1_1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell1_2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell1_3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell2_0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell2_1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell2_2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Body_Shell2_3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_BrowL_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_BrowR_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_CheekL_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_CheekR_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_Chin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_EyeL_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_EyeR_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_JawCavity_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothL0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothL1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothL2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothL3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothR0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothR1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothR2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_LowerToothR3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_MouthEmber_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothL0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothL1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothL2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothL3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothR0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothR1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothR2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: Head_UpperToothR3_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_AnklePin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_AnklePivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_AnkleRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_HipPin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_HipPivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_HipRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_InnerShin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_InnerThigh_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_KneeGuard_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_KneePin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_KneePivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_KneeRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_ShinArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_ThighArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_Toe0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_Toe1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_Toe2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_ToeCap0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_ToeCap1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegL_ToeCap2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_AnklePin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_AnklePivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_AnkleRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_HipPin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_HipPivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_HipRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_InnerShin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_InnerThigh_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_KneeGuard_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_KneePin_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_KneePivot_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_KneeRim_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_ShinArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_ThighArmor_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_Toe0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_Toe1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_Toe2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_ToeCap0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_ToeCap1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: LegR_ToeCap2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponL_Claw0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponL_Claw1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponL_Claw2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponR_Claw0_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponR_Claw1_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Extracting primitive: WeaponR_Claw2_Mesh.001 +20:56:39 | INFO: Primitives created: 1 +20:56:39 | INFO: Finished glTF 2.0 export in 0.1974790096282959 s +00:14.739 blend | Read blend: "/tmp/saumwacht-standalone-odcjpne_/blend/n08.blend" + +EXPORTED g01: 79780 triangles, 131 parts -> /tmp/saumwacht-standalone-odcjpne_/exports/unit_g01.glb +STANDALONE_PASS: g01 +KEEP_SCENE_PASS: two generated scenes and original scene retained +Warnung: Bibliotheksdatei, lädt leere Szene +NATIVE_BLEND_PASS: isolated N08 scene reopened; 20 objects +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/standalone-verify.log b/docs/phase10-logs/standalone-verify.log new file mode 100644 index 0000000..e18fb15 --- /dev/null +++ b/docs/phase10-logs/standalone-verify.log @@ -0,0 +1,2938 @@ +00:00.016 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.016 color_management | Using fallback mode for management +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:48:28 | INFO: Starting glTF 2.0 export +20:48:28 | INFO: Extracting primitive: ArmL0_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL0_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL0_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL0_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL1_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL1_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL1_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL1_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL2_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL2_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL2_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL2_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmL_Shoulder_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR0_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR0_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR0_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR0_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR1_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR1_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR1_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR1_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR2_Housing_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR2_Pivot_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR2_Pivot_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR2_Rod_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: ArmR_Shoulder_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Body_Breastplate_Face_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Body_Breastplate_Rim_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Body_HipPlateL_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Body_HipPlateR_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Body_Waist_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Head_Eye1_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Head_Face_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_AnkleGold_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Greave_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Knee_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Knee_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Piston_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Shin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_ThighArmor_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Toe0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg0_Toe1_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_AnkleGold_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Greave_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Knee_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Knee_Pin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Piston_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Shin_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_ThighArmor_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Toe0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: Leg1_Toe1_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponL0_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponL1_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponL2_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponR0_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponR1_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Extracting primitive: WeaponR2_Blade0_Mesh +20:48:28 | INFO: Primitives created: 1 +20:48:28 | INFO: Finished glTF 2.0 export in 0.06307029724121094 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_tank.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_tank.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED m04: 1398 triangles, 60 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_m04.glb +STANDALONE_PASS: m04 +20:48:31 | INFO: Starting glTF 2.0 export +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +20:48:31 | INFO: Primitives created: 1 +20:48:31 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_BorderL_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_BorderR_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestL_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestR_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_SeamL_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_SeamR_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Body_SpineGold_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_Fire_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:48:32 | INFO: Primitives created: 1 +20:48:32 | INFO: Finished glTF 2.0 export in 0.2988460063934326 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_ranged.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_ranged.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED g04: 80764 triangles, 220 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_g04.glb +STANDALONE_PASS: g04 +20:48:33 | INFO: Starting glTF 2.0 export +20:48:33 | INFO: Extracting primitive: Body_Braid0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_Seed_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Moss_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Moss_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Finished glTF 2.0 export in 0.31298279762268066 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_artillery.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w06: 62588 triangles, 296 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_w06.glb +STANDALONE_PASS: w06 +20:48:33 | INFO: Starting glTF 2.0 export +20:48:33 | INFO: Extracting primitive: ArmL_Sickle_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: ArmR_Sickle_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_ArchMask_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_ArchMask_Eye1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_ArchMask_Eye_1_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_BellSkirt_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_CathedralFrontArch_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_CathedralShell_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_CentralFlow_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TailL_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_TailR_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_WispL_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Body_WispR_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_CentralSpire_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SpireL_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Head_SpireR_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Weapon_Clapper_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Extracting primitive: Weapon_ClapperChain_Mesh +20:48:33 | INFO: Primitives created: 1 +20:48:33 | INFO: Finished glTF 2.0 export in 0.024341106414794922 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_support.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_support.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED n08: 1482 triangles, 18 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_n08.glb +STANDALONE_PASS: n08 +20:48:35 | INFO: Starting glTF 2.0 export +20:48:35 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Moss_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Moss_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Extracting primitive: Weapon_Water_Mesh +20:48:35 | INFO: Primitives created: 1 +20:48:35 | INFO: Finished glTF 2.0 export in 0.36241936683654785 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_mercenary.py:234: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w10: 61052 triangles, 348 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_w10.glb +STANDALONE_PASS: w10 +20:48:36 | INFO: Starting glTF 2.0 export +20:48:36 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Lower_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_PauldronCap_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Lower_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_PauldronCap_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Armor_Face_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Armor_Rim_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Belt_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Tabard_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_Crest_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_Eye1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_HelmetBack_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_Visor_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_VisorSlit_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegL_Boot_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegL_KneePlate_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegL_Shin_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegL_Strap_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegL_Thigh_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegR_Boot_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegR_KneePlate_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegR_Shin_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegR_Strap_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: LegR_Thigh_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Weapon_Haft_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Weapon_Head_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Weapon_TriangleInset_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Weapon_TriangleRim_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Weapon_Wedge_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Finished glTF 2.0 export in 0.04970717430114746 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_worker.py:190: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_worker.py:460: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED s04: 10458 triangles, 35 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_s04.glb +STANDALONE_PASS: s04 +20:48:36 | INFO: Starting glTF 2.0 export +20:48:36 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Finger0_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Finger1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Finger2_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Forearm_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Finger0_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Finger1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Finger2_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Forearm_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet0_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet2_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet3_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet4_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet5_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ApronRivet6_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ClayTorso_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Harness1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Harness_1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_LeatherApron_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_Reservoir_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace0_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace2_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace3_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace4_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace5_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace6_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankBrace7_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankRim0_45_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_TankRim0_79_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Body_ToolPocket_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_Cap_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_FaceRecess_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_GoggleGlint1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_GoggleGlint_1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_GoggleLens1_Mesh +20:48:36 | INFO: Primitives created: 1 +20:48:36 | INFO: Extracting primitive: Head_GoggleLens_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Head_GoggleSocket1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Head_GoggleSocket_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Head_Hood_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Head_Lamp_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Head_LampHousing_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_Boot_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_Cuff_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_Shin_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_Sole_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_ToeRidge0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_ToeRidge1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegL_ToeRidge2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_Boot_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_Cuff_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_Shin_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_Sole_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_ToeRidge0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_ToeRidge1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: LegR_ToeRidge2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: WeaponL_Fork_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: WeaponL_Handle_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: WeaponR_Probe_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Finished glTF 2.0 export in 0.08774614334106445 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_lane.py:189: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_lane.py:459: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED worker: 24026 triangles, 65 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/worker.glb +STANDALONE_PASS: worker +20:48:37 | INFO: Starting glTF 2.0 export +20:48:37 | INFO: Extracting primitive: Body_EdgeCap1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap1_2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap1_3_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap_1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap_1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap_1_2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeCap_1_3_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone1_2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone1_3_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone_1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone_1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone_1_2_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_EdgeStone_1_3_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneFoundation_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_00_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_01_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_02_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_03_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_04_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LaneSlab_05_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LBasalt_00_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LBasalt_01_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LBasalt_02_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LBrassMarker_00_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LBrassMarker_01_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightGlass1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightGlass1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightGlass_1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightGlass_1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightRecess1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightRecess1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightRecess_1_0_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LightRecess_1_1_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LMoss_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_LRetainingLip_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RBasalt_00_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RBasalt_01_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RBasalt_02_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RBrassMarker_00_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RBrassMarker_01_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RMoss_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Extracting primitive: Body_RRetainingLip_Mesh +20:48:37 | INFO: Primitives created: 1 +20:48:37 | INFO: Finished glTF 2.0 export in 0.09453177452087402 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_core.py:203: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_core.py:473: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_core.py:1365: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + +EXPORTED map_lane_segment: 10700 triangles, 45 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/map_lane_segment.glb +STANDALONE_PASS: map_lane_segment +20:48:38 | INFO: Starting glTF 2.0 export +20:48:38 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal5_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal6_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal7_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal8_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal9_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal10_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Body_Seal11_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Team_Triangle0_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Team_Triangle1_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Extracting primitive: Team_Triangle2_Mesh +20:48:38 | INFO: Primitives created: 1 +20:48:38 | INFO: Finished glTF 2.0 export in 0.10146856307983398 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED core_team1: 36848 triangles, 66 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/core_team1.glb +STANDALONE_PASS: core_team1 +STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved +20:48:40 | INFO: Starting glTF 2.0 export +20:48:40 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_LavaCore_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell0_0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell0_1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell0_2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell0_3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell1_0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell1_1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell1_2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell1_3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell2_0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell2_1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell2_2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Body_Shell2_3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_BrowL_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_BrowR_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_CheekL_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_CheekR_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_Chin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_EyeL_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_EyeR_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_JawCavity_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_MouthEmber_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +20:48:40 | INFO: Primitives created: 1 +20:48:40 | INFO: Finished glTF 2.0 export in 0.2310781478881836 s +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-rxfdxe8j/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED g01: 79780 triangles, 131 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_g01.glb +STANDALONE_PASS: g01 +20:48:42 | INFO: Starting glTF 2.0 export +20:48:42 | INFO: Extracting primitive: ArmL_Elbow_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Palm_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_Shoulder_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_UpperBand_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_UpperCore_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_WristBand_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Elbow_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Palm_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_Shoulder_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_UpperBand_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_UpperCore_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_WristBand_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_LavaCore_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell0_0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell0_1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell0_2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell0_3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell1_0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell1_1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell1_2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell1_3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell2_0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell2_1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell2_2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Body_Shell2_3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_BrowL_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_BrowR_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_CheekL_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_CheekR_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_Chin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_EyeL_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_EyeR_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_JawCavity_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothL0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothL1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothL2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothL3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothR0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothR1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothR2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_LowerToothR3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_MouthEmber_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothL0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothL1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothL2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothL3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothR0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothR1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothR2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: Head_UpperToothR3_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_AnklePin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_AnklePivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_AnkleRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_HipPin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_HipPivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_HipRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_InnerShin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_InnerThigh_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_KneeGuard_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_KneePin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_KneePivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_KneeRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_ShinArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_ThighArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_Toe0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_Toe1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_Toe2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_ToeCap0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_ToeCap1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegL_ToeCap2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_AnklePin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_AnklePivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_AnkleRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_HipPin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_HipPivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_HipRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_InnerShin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_InnerThigh_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_KneeGuard_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_KneePin_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_KneePivot_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_KneeRim_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_ShinArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_ThighArmor_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_Toe0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_Toe1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_Toe2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_ToeCap0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_ToeCap1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: LegR_ToeCap2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponL_Claw0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponL_Claw1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponL_Claw2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponR_Claw0_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponR_Claw1_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Extracting primitive: WeaponR_Claw2_Mesh.001 +20:48:42 | INFO: Primitives created: 1 +20:48:42 | INFO: Finished glTF 2.0 export in 0.21325397491455078 s +00:15.777 blend | Read blend: "/tmp/saumwacht-standalone-rxfdxe8j/blend/n08.blend" + +EXPORTED g01: 79780 triangles, 131 parts -> /tmp/saumwacht-standalone-rxfdxe8j/exports/unit_g01.glb +STANDALONE_PASS: g01 +KEEP_SCENE_PASS: two generated scenes and original scene retained +Warnung: Bibliotheksdatei, lädt leere Szene +NATIVE_BLEND_PASS: isolated N08 scene reopened; 20 objects +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/texture-output.log b/docs/phase10-logs/texture-output.log new file mode 100644 index 0000000..da1b385 --- /dev/null +++ b/docs/phase10-logs/texture-output.log @@ -0,0 +1,8 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +OUTPUT /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/materials/phase10/oak-height-4k.png 16658293 +OUTPUT /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/materials/phase10/oak-albedo-4k.png 16231624 +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase10-logs/ui-vulkan.log b/docs/phase10-logs/ui-vulkan.log new file mode 100644 index 0000000..7c74487 --- /dev/null +++ b/docs/phase10-logs/ui-vulkan.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /tmp/sw10-ui-vulkan/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/visual-first.log b/docs/phase10-logs/visual-first.log new file mode 100644 index 0000000..5115753 --- /dev/null +++ b/docs/phase10-logs/visual-first.log @@ -0,0 +1,26 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +--res://scripts/presentation/sanctuary.gdshader-- + 29 | float broad=noise(world*.8); + 30 | float relief=dot(stone,vec3(.333)); +E 31-> ALBEDO=base_color.rgb*mix(.65,1.6,stone); + 32 | ROUGHNESS=.88; + 33 | if(paving) { ALBEDO=base_color.rgb*mix(.82,1.3,stone); } +SHADER ERROR: Invalid arguments for the built-in function: "mix(float,float,vec3)". + at: (null) (res://scripts/presentation/sanctuary.gdshader:31) + GDScript backtrace (most recent call first): + [0] _decorate (res://scripts/presentation/sanctuary.gd:66) + [1] _decorate (res://scripts/presentation/sanctuary.gd:76) + [2] _ready (res://scripts/presentation/sanctuary.gd:12) + [3] _make_world (res://scripts/main.gd:426) + [4] _ready (res://scripts/main.gd:36) +ERROR: Shader compilation failed. + at: set_code (servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp:185) + GDScript backtrace (most recent call first): + [0] _decorate (res://scripts/presentation/sanctuary.gd:66) + [1] _decorate (res://scripts/presentation/sanctuary.gd:76) + [2] _ready (res://scripts/presentation/sanctuary.gd:12) + [3] _make_world (res://scripts/main.gd:426) + [4] _ready (res://scripts/main.gd:36) +FACTION_PASS: 123 checks; 0 failures; /tmp/sw10-visual/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-logs/visual-second.log b/docs/phase10-logs/visual-second.log new file mode 100644 index 0000000..b163b5b --- /dev/null +++ b/docs/phase10-logs/visual-second.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 123 checks; 0 failures; /tmp/sw10-visual2/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase10-package-check.json b/docs/phase10-package-check.json new file mode 100644 index 0000000..554d859 --- /dev/null +++ b/docs/phase10-package-check.json @@ -0,0 +1,33 @@ +{ + "version": "0.10.0", + "packages": [ + { + "platform": "Linux", + "executable": "linux/Saumwacht.x86_64", + "exe_bytes": 241156560, + "archive": "Saumwacht-Linux-x64-0.10.0.zip", + "archive_bytes": 183333861, + "sha256": "a2d60a5e5947575899045b99a0f27a549e2f71539014591210db0c978c492ccb", + "exe_sha256": "7722762ff3e91d952ca364c0b740cf039bda8ac0180f6906c0da95f6c9b25a49", + "crc": "OK", + "archive_sha256_matches": true, + "extracted_sha256_matches": true, + "font_license_included": true, + "extracted_executable": "/tmp/saumwacht-010-package-check/Saumwacht-Linux/Saumwacht.x86_64" + }, + { + "platform": "Windows", + "executable": "windows/Saumwacht.exe", + "exe_bytes": 276905632, + "archive": "Saumwacht-Windows-x64-0.10.0.zip", + "archive_bytes": 193250086, + "sha256": "4f0d3b46d9ded5091644da2c7306694d55712f9c2d015ecc796b7ecc0d9c5985", + "exe_sha256": "23731769f26d5eed6e80a7bdf8fd14020fdc16b70befeb384a76c7ba7e6b7c0f", + "crc": "OK", + "archive_sha256_matches": true, + "extracted_sha256_matches": true, + "font_license_included": true, + "extracted_executable": "/tmp/saumwacht-010-package-check/Saumwacht-Windows/Saumwacht.exe" + } + ] +} diff --git a/docs/phase10-package-full-visual.json b/docs/phase10-package-full-visual.json new file mode 100644 index 0000000..b250d27 --- /dev/null +++ b/docs/phase10-package-full-visual.json @@ -0,0 +1,5504 @@ +{ + "checks": 1684, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase10-package-linux.json b/docs/phase10-package-linux.json new file mode 100644 index 0000000..89cf0cb --- /dev/null +++ b/docs/phase10-package-linux.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase10-package-opengl.json b/docs/phase10-package-opengl.json new file mode 100644 index 0000000..19cbe33 --- /dev/null +++ b/docs/phase10-package-opengl.json @@ -0,0 +1,7 @@ +{ + "checks": 128, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase10-package-vulkan.json b/docs/phase10-package-vulkan.json new file mode 100644 index 0000000..1469139 --- /dev/null +++ b/docs/phase10-package-vulkan.json @@ -0,0 +1,7 @@ +{ + "checks": 128, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase10-package-windows.json b/docs/phase10-package-windows.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase10-package-windows.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase10-runtime.json b/docs/phase10-runtime.json new file mode 100644 index 0000000..9ef9649 --- /dev/null +++ b/docs/phase10-runtime.json @@ -0,0 +1,18 @@ +{ + "audio_events": 120, + "checks": 9, + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "4.7.2-stable (fedora)", + "failures": [], + "frames": 1726, + "max_draw_calls": 5064, + "mean_fps": 143.82613004132, + "mean_frame_ms": 6.95283951332561, + "p95_frame_ms": 12.152, + "renderer": "forward_plus", + "sample_seconds": 12, + "speed": 2, + "units_at_start": 86, + "viewport": "(1600.0, 960.0)", + "wave": 20 +} \ No newline at end of file diff --git a/docs/phase10-verification.json b/docs/phase10-verification.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase10-verification.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase10-visual-verification.json b/docs/phase10-visual-verification.json new file mode 100644 index 0000000..50313cc --- /dev/null +++ b/docs/phase10-visual-verification.json @@ -0,0 +1,7 @@ +{ + "checks": 128, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase11-QA.md b/docs/phase11-QA.md new file mode 100644 index 0000000..440a769 --- /dev/null +++ b/docs/phase11-QA.md @@ -0,0 +1,27 @@ +# Ringborke · Demo 0.11.0 + +Stand: **19. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. Die Pakete verwenden das offizielle Release-Template `ed1daf0bf`. + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Ringborke: exportierte Geometrie, Gewichte und Clips | 30 bestanden | +| Ringborke: Godot-Skelett und Kampfanbindung | 33 bestanden | +| Quellprojekt: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Entpacktes Linux-Paket: Grafiklauf und vier KI-Partien bis Welle 20 | 1.684 bestanden | +| Windows-PCK mit Linux-Godot: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Beide Pakete: Kurzpartie, Assets, Audio, Modellbetrachter und Optionen | jeweils 271 bestanden | +| Beiliegender Linux-Kompatibilitätsstarter: OpenGL-Bedienprüfung | 128 bestanden | +| Archive und extrahierte Programme | CRC und SHA-256 stimmen überein | +| Nativer Windows-Lauf | Nicht durchgeführt | + +Alle genannten automatischen Prüfungen enden ohne fehlgeschlagene Checks. Die Ringborke besitzt **118.064 Dreiecke, 27 Knochen und neun Bewegungen**. Von 59.956 Vertices verwenden 15.442 mehrere Knochengewichte (25,76 %). + +| Reguläres Duell | Letzte Welle | Kern-HP | +| --- | ---: | ---: | +| Wurzelbund → Glutpakt | 20 | 1.244 / 1.709 | +| Glutpakt → Wurzelbund | 20 | 1.709 / 1.244 | +| Wurzelbund → Wurzelbund | 20 | 1.244 / 1.244 | +| Wurzelbund-Spiegel, Kurzpartie | 8 | 3.000 / 3.000 | + +[Geometrie und Skin](phase11-skin-audit.json) · [Skelettprüfung](phase11-rig-verification.json) · [Pakete](phase11-builds.md) · [Modellbericht](../../docs/phase-11-ringborke.md). diff --git a/docs/phase11-benchmark.json b/docs/phase11-benchmark.json new file mode 100644 index 0000000..f45d994 --- /dev/null +++ b/docs/phase11-benchmark.json @@ -0,0 +1,78 @@ +{ + "device": "NVIDIA GeForce RTX 5060 Ti", + "msaa": "4x", + "render_target": "Fixed-size SubViewport independent of desktop DPI and window stretch", + "renderer": "forward_plus", + "results": [ + { + "draw_calls": 17.0, + "fps": 1230.19657648058, + "instances": 1, + "mean_frame_ms": 0.81287821728529, + "p95_frame_ms": 1.339, + "render_size": "(1920.0, 1080.0)", + "resolution": "(1920, 1080)", + "video_memory_bytes": 596717552.0, + "window_size": "(960, 540)" + }, + { + "draw_calls": 481.0, + "fps": 607.154928338054, + "instances": 30, + "mean_frame_ms": 1.64702607740872, + "p95_frame_ms": 2.508, + "render_size": "(1920.0, 1080.0)", + "resolution": "(1920, 1080)", + "video_memory_bytes": 631530080.0, + "window_size": "(960, 540)" + }, + { + "draw_calls": 1441.0, + "fps": 344.446094186261, + "instances": 90, + "mean_frame_ms": 2.90321190130623, + "p95_frame_ms": 3.527, + "render_size": "(1920.0, 1080.0)", + "resolution": "(1920, 1080)", + "video_memory_bytes": 703556000.0, + "window_size": "(960, 540)" + }, + { + "draw_calls": 17.0, + "fps": 817.131393828169, + "instances": 1, + "mean_frame_ms": 1.22379339180093, + "p95_frame_ms": 1.82, + "render_size": "(2560.0, 1440.0)", + "resolution": "(2560, 1440)", + "video_memory_bytes": 790753264.0, + "window_size": "(960, 540)" + }, + { + "draw_calls": 481.0, + "fps": 415.938371797913, + "instances": 30, + "mean_frame_ms": 2.40420232371794, + "p95_frame_ms": 3.28, + "render_size": "(2560.0, 1440.0)", + "resolution": "(2560, 1440)", + "video_memory_bytes": 825565792.0, + "window_size": "(960, 540)" + }, + { + "draw_calls": 1441.0, + "fps": 276.798595109647, + "instances": 90, + "mean_frame_ms": 3.61273509933774, + "p95_frame_ms": 4.534, + "render_size": "(2560.0, 1440.0)", + "resolution": "(2560, 1440)", + "video_memory_bytes": 897591712.0, + "window_size": "(960, 540)" + } + ], + "sample_seconds": 6, + "scope": "Isolated animated characters; not a complete game benchmark; includes CPU and GPU frame pacing, not separately timed stages", + "vsync": false, + "warmup_seconds": 2 +} \ No newline at end of file diff --git a/docs/phase11-builds.md b/docs/phase11-builds.md new file mode 100644 index 0000000..01b504e --- /dev/null +++ b/docs/phase11-builds.md @@ -0,0 +1,42 @@ +# Demo 0.11.0 · Windows und Linux + +Stand: 19. September 2026. Die Ringborke ist als erste Musterfigur neu aufgebaut: gewichtetes Skelett, neun Bewegungen und native 4K-Holzschnittmaterialien. Enthalten bleiben Glutpakt, Wurzelbund, 8/20 Wellen, Rivalen-KI, Ruinenlandschaft und das bisher überarbeitete Interface. + +| System | Paket | Größe | +| --- | --- | ---: | +| Windows | [Saumwacht-Windows-x64-0.11.0.zip](../../dist/Saumwacht-Windows-x64-0.11.0.zip) | 227,2 MiB | +| Linux | [Saumwacht-Linux-x64-0.11.0.zip](../../dist/Saumwacht-Linux-x64-0.11.0.zip) | 217,8 MiB | + +ZIP vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh` oder `Saumwacht.x86_64`. Godot und Blender werden zum Spielen nicht benötigt. Spieldaten sind eingebettet. Beide Archive enthalten Anleitung, Lizenzen und einen OpenGL-Kompatibilitätsstarter. Frühere versionierte Archive bleiben erhalten. + +**V → Ringborke** öffnet die neue Figur. Im Betrachter eine Bewegung auswählen; Pause und Zeitleiste erlauben die Betrachtung einzelner Posen. `Saumwacht.exe -- --ringborke` beziehungsweise `./Saumwacht.x86_64 -- --ringborke` öffnet ihn direkt. [Video aus dem tatsächlichen Godot-Betrachter](screenshots/phase11/ringborke-animation.mp4). + +Für eine Partie Bund, Rivalen und Länge wählen, danach **Startformation** kaufen. Bauphase und Abrechnung warten auf die Leertaste. C wechselt zur Basis; F1 öffnet Optionen. Mit V lässt sich der Betrachter jederzeit öffnen und schließen. Die Ringborke ist die aufgewertete Wurzelbund-Einheit W04. Andere Figuren haben weiterhin ihre bisherigen Gelenkanimationen. + +## Paketprüfung + +Die Archive bestehen CRC- und SHA-256-Prüfung. Die Hashes der extrahierten Programme stimmen mit dem Buildmanifest überein. Alle folgenden Prüfungen liefen außerhalb des Quellprojekts: + +- Linux mit Vulkan: **1.684** Prüfungen einschließlich Bedienung, Fähigkeiten und vier vollständiger KI-Partien, keine Fehler. +- Windows-Spieldaten mit Linux-Godot: **1.665** Prüfungen einschließlich derselben vier Partien, keine Fehler. +- Beide Pakete: je **271** Kurzpartie-, Asset-, Audio-, Betrachter- und Optionsprüfungen, keine Fehler. +- Beiliegender Linux-Kompatibilitätsstarter: **128** OpenGL-Bedienprüfungen, keine Fehler. Die neuen Modell-Spieldaten wurden zusätzlich mit Linux-Godot im OpenGL-Modus dargestellt. + +**Ein nativer Windows-Lauf wurde nicht durchgeführt.** Der Windows-PCK-Test bestätigt Spieldaten und Skripte, nicht den Windows-Prozess, Treiber oder Audiogeräte. Die EXE ist nicht signiert. + +[Prüfbericht](QA.md) · [Paketintegrität](phase11-package-check.json) · [Linux-Partien mit Grafik](phase11-package-linux.json) · [Windows-PCK](phase11-package-windows.json) · [OpenGL](phase11-package-opengl.json). + +## Wiederaufbau + +`python3 tools/build_demo.py` aus `saumwacht-godot` nutzt die vorhandenen offiziellen Godot-4.7.2-Release-Templates. Aktualisiert werden die versionierten Archive, `dist/build-manifest.json`, `dist/SHA256SUMS.txt` und die entpackten Ordner `dist/linux` und `dist/windows`. Quellen, Dokumentation und Entwicklungswerkzeuge bleiben außerhalb des Exports. Die im GLB importierten Texturen werden mitgeliefert; ihre zusätzlichen Rohdateien im Materialquellordner werden nicht doppelt verpackt. + +Automatische Tests sollten eigene `XDG_DATA_HOME`- und `XDG_CONFIG_HOME`-Ordner verwenden. Vorhandene Nutzereinstellungen bleiben unter dem historischen Namen `Saumwacht · Glutpakt` erhalten. + +## SHA-256 + +```text +7cc8ab4ebf27b1f14fd66bc337a1c01f0b669f98bda3ed47fa7e8c31948e3692 Saumwacht-Linux-x64-0.11.0.zip +eef9e6136d628a233c25be04bdbd86e57fc32c21f0b0f1168b5c79ef5c0d5da3 Saumwacht-Windows-x64-0.11.0.zip +``` + +[Modellbericht, Blender-Datei und Animationen](../../docs/phase-11-ringborke.md) · [Vorherige Demo 0.10](phase10-builds.md). diff --git a/docs/phase11-faction-verification.json b/docs/phase11-faction-verification.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase11-faction-verification.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase11-logs/benchmark-final.log b/docs/phase11-logs/benchmark-final.log new file mode 100644 index 0000000..6f50ee3 --- /dev/null +++ b/docs/phase11-logs/benchmark-final.log @@ -0,0 +1,9 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(960, 540)", "render_size": "(1920.0, 1080.0)", "instances": 1, "mean_frame_ms": 0.81287821728529, "p95_frame_ms": 1.339, "draw_calls": 17.0, "video_memory_bytes": 596717552.0, "fps": 1230.19657648058 } +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(960, 540)", "render_size": "(1920.0, 1080.0)", "instances": 30, "mean_frame_ms": 1.64702607740872, "p95_frame_ms": 2.508, "draw_calls": 481.0, "video_memory_bytes": 631530080.0, "fps": 607.154928338054 } +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(960, 540)", "render_size": "(1920.0, 1080.0)", "instances": 90, "mean_frame_ms": 2.90321190130623, "p95_frame_ms": 3.527, "draw_calls": 1441.0, "video_memory_bytes": 703556000.0, "fps": 344.446094186261 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(960, 540)", "render_size": "(2560.0, 1440.0)", "instances": 1, "mean_frame_ms": 1.22379339180093, "p95_frame_ms": 1.82, "draw_calls": 17.0, "video_memory_bytes": 790753264.0, "fps": 817.131393828169 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(960, 540)", "render_size": "(2560.0, 1440.0)", "instances": 30, "mean_frame_ms": 2.40420232371794, "p95_frame_ms": 3.28, "draw_calls": 481.0, "video_memory_bytes": 825565792.0, "fps": 415.938371797913 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(960, 540)", "render_size": "(2560.0, 1440.0)", "instances": 90, "mean_frame_ms": 3.61273509933774, "p95_frame_ms": 4.534, "draw_calls": 1441.0, "video_memory_bytes": 897591712.0, "fps": 276.798595109647 } diff --git a/docs/phase11-logs/benchmark.log b/docs/phase11-logs/benchmark.log new file mode 100644 index 0000000..ec24002 --- /dev/null +++ b/docs/phase11-logs/benchmark.log @@ -0,0 +1,9 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(1920, 1080)", "render_size": "(2025.0, 1215.0)", "instances": 1, "mean_frame_ms": 0.84327364722417, "p95_frame_ms": 1.399, "draw_calls": 16.0, "video_memory_bytes": 575463408.0, "fps": 1185.85467871755 } +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(1920, 1080)", "render_size": "(2025.0, 1215.0)", "instances": 30, "mean_frame_ms": 1.70697553342817, "p95_frame_ms": 2.469, "draw_calls": 480.0, "video_memory_bytes": 610275936.0, "fps": 585.831478200318 } +RIG_BENCH: { "resolution": "(1920, 1080)", "window_size": "(1920, 1080)", "render_size": "(2025.0, 1215.0)", "instances": 90, "mean_frame_ms": 3.39473571024335, "p95_frame_ms": 4.642, "draw_calls": 1440.0, "video_memory_bytes": 682301856.0, "fps": 294.573741626654 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(2560, 1440)", "render_size": "(3600.0, 2160.0)", "instances": 1, "mean_frame_ms": 1.28598114016288, "p95_frame_ms": 1.868, "draw_calls": 16.0, "video_memory_bytes": 756539632.0, "fps": 777.616380807374 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(2560, 1440)", "render_size": "(3600.0, 2160.0)", "instances": 30, "mean_frame_ms": 2.47874514663363, "p95_frame_ms": 3.179, "draw_calls": 480.0, "video_memory_bytes": 791352160.0, "fps": 403.429937667491 } +RIG_BENCH: { "resolution": "(2560, 1440)", "window_size": "(2560, 1440)", "render_size": "(3600.0, 2160.0)", "instances": 90, "mean_frame_ms": 3.85480398457584, "p95_frame_ms": 5.024, "draw_calls": 1440.0, "video_memory_bytes": 863378080.0, "fps": 259.416562813902 } diff --git a/docs/phase11-logs/blender-build.log b/docs/phase11-logs/blender-build.log new file mode 100644 index 0000000..cfcdd61 --- /dev/null +++ b/docs/phase11-logs/blender-build.log @@ -0,0 +1,23 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +/home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets-source/phase11/build_ringborke.py:20: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + m=bpy.data.materials.new('RB_'+name);m.diffuse_color=(*color,1);m.use_nodes=True +00:02.696 image.write | ERROR OpenImageIO write failed: Could not open file "/home/martin/.cache/thumbnails/large/blender_4_f3dc85b8865a40f35466dc8484ef6a62.png.png" +00:02.728 image.write | ERROR OpenImageIO write failed: Could not open file "/home/martin/.cache/thumbnails/large/blender_4_f3dc85b8865a40f35466dc8484ef6a62.png.png" +Extensions: writing cache failed ([Errno 30] Read-only file system: '/home/martin/.config/blender/5.2/extensions'). +Info: Saved as "ringborke.blend" +Info: Total files 4 | Changed 0 | Failed 0 +Info: Saved as "ringborke.blend" +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +15:53:11 | INFO: Starting glTF 2.0 export +15:53:11 | INFO: Extracting primitive: Trunk +15:53:13 | WARNING: The active Vertex Color will not be exported, as it is not used in the node tree of the material +15:53:13 | INFO: Primitives created: 8 +15:53:14 | INFO: Finished glTF 2.0 export in 2.5479812622070312 s + +RINGBORKE_BUILD 118064 triangles 27 bones 9 clips +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase11-logs/builds.log b/docs/phase11-logs/builds.log new file mode 100644 index 0000000..c703517 --- /dev/null +++ b/docs/phase11-logs/builds.log @@ -0,0 +1,2 @@ +Linux: Saumwacht-Linux-x64-0.11.0.zip (217.8 MiB) +Windows: Saumwacht-Windows-x64-0.11.0.zip (227.2 MiB) diff --git a/docs/phase11-logs/faction.log b/docs/phase11-logs/faction.log new file mode 100644 index 0000000..0b9bbcf --- /dev/null +++ b/docs/phase11-logs/faction.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/sw11-faction/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase11-logs/import-final.log b/docs/phase11-logs/import-final.log new file mode 100644 index 0000000..5be25af --- /dev/null +++ b/docs/phase11-logs/import-final.log @@ -0,0 +1,71 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] _update_scan_actions | Started Aktionen scannen … (4 steps) +[ 0% ] _update_scan_actions | ringborke_oak-height-4k.png +[ 20% ] _update_scan_actions | ringborke_ringborke-cut-albedo-4k.png +[ 40% ] _update_scan_actions | ringborke_ringborke-cut-normal-4k.png +[ 60% ] _update_scan_actions | ringborke_ringborke-cut-roughness-4k.png +[ DONE ] _update_scan_actions + +[ 0% ] reimport | Started Assets (erneut) importieren (4 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 20% ] reimport | Dateien zum Neuimport vorbereiten … +[ 40% ] reimport | Dateien zum Neuimport vorbereiten … +[ 60% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 20% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 40% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 40% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 40% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 40% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 40% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 60% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 60% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 60% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 60% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 60% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 80% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (4 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase11-logs/import.log b/docs/phase11-logs/import.log new file mode 100644 index 0000000..876ceab --- /dev/null +++ b/docs/phase11-logs/import.log @@ -0,0 +1,60 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) +[ 0% ] first_scan_filesystem | Started Projektinitialisierung (5 steps) +[ 0% ] first_scan_filesystem | Lese Dateistrucktur … +[ 16% ] first_scan_filesystem | Globale Klassennamen laden … +[ 33% ] first_scan_filesystem | Verifiziere GDExtensions… +[ 50% ] first_scan_filesystem | Autoload-Skripte erzeugen … +[ 66% ] first_scan_filesystem | Plugins initialisieren… +[ 83% ] first_scan_filesystem | Dateiscan starten … +[ DONE ] first_scan_filesystem + +[ 0% ] reimport | Started Assets (erneut) importieren (5 steps) +[ 0% ] reimport | Dateien zum Neuimport vorbereiten … +[ 16% ] reimport | Dateien zum Neuimport vorbereiten … +[ 33% ] reimport | Dateien zum Neuimport vorbereiten … +[ 50% ] reimport | Dateien zum Neuimport vorbereiten … +[ 66% ] reimport | Dateien zum Neuimport vorbereiten … +[ 0% ] reimport | Vor-Neuimport-Operationen ausführen … +[ 0% ] preload_reimporting_scene | Started Szenen zum Neuladen vorbereiten (1 steps) +[ 0% ] preload_reimporting_scene | Szene [leer] wird analysiert +[ 50% ] preload_reimporting_scene | Vorbereitung abgeschlossen. +[ DONE ] preload_reimporting_scene + +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 0% ] reimport | ringborke_oak-height-4k.png +[ 16% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 16% ] reimport | ringborke_ringborke-cut-albedo-4k.png +[ 33% ] reimport | ringborke_ringborke-cut-roughness-4k.png +[ 50% ] reimport | ringborke_ringborke-cut-normal-4k.png +[ 66% ] reimport | ringborke.glb +[ 0% ] import | Started Szene importieren (104 steps) +[ 0% ] import | Importiere Szene… +[ 1% ] import | Eigenes Skript wird ausgeführt … +[ 99% ] import | Speichern … +[ DONE ] import + +[ 83% ] reimport | Asset-Import fertigstellen … +[ DONE ] reimport + +[ 0% ] reimport | Started Assets (erneut) importieren (5 steps) +[ 0% ] reimport | Nach-Neuimport-Operationen ausführen … +[ DONE ] reimport + +[ 0% ] loading_editor_layout | Started Editor laden (5 steps) +[ 0% ] loading_editor_layout | Editor-Layout laden … +[ 16% ] loading_editor_layout | Docks laden … +[ 33% ] loading_editor_layout | Öffne Szenen neu… +[ 50% ] loading_editor_layout | Zentrales Editor-Layout laden … +[ 66% ] loading_editor_layout | Pluginfensterlayout laden … +[ 83% ] loading_editor_layout | Editorlayout bereit. +[ DONE ] loading_editor_layout + +ERROR: Condition "_sock == -1" is true. Returning: FAILED + at: _inet_open (drivers/unix/net_socket_unix.cpp:288) +ERROR: Condition "err != OK" is true. Returning: ERR_CANT_CREATE + at: listen (core/io/tcp_server.cpp:56) diff --git a/docs/phase11-logs/material-bake.log b/docs/phase11-logs/material-bake.log new file mode 100644 index 0000000..f199613 --- /dev/null +++ b/docs/phase11-logs/material-bake.log @@ -0,0 +1,7 @@ +00:00.015 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.015 color_management | Using fallback mode for management +CUTWOOD_BAKE_PASS: three native 4096px material maps +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase11-logs/package-full.log b/docs/phase11-logs/package-full.log new file mode 100644 index 0000000..307a707 --- /dev/null +++ b/docs/phase11-logs/package-full.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1684 checks; 0 failures; /tmp/sw11-package-full/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase11-logs/package-opengl-model.log b/docs/phase11-logs/package-opengl-model.log new file mode 100644 index 0000000..c75e651 --- /dev/null +++ b/docs/phase11-logs/package-opengl-model.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +RINGBORKE_OPENGL_PACKAGE_PASS diff --git a/docs/phase11-logs/package-opengl.log b/docs/phase11-logs/package-opengl.log new file mode 100644 index 0000000..4203c3d --- /dev/null +++ b/docs/phase11-logs/package-opengl.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /tmp/sw11-package-opengl/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase11-logs/package-smoke.log b/docs/phase11-logs/package-smoke.log new file mode 100644 index 0000000..47b7dd6 --- /dev/null +++ b/docs/phase11-logs/package-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 271 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw11-package-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase11-logs/package-windows-smoke.log b/docs/phase11-logs/package-windows-smoke.log new file mode 100644 index 0000000..d0260bd --- /dev/null +++ b/docs/phase11-logs/package-windows-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 271 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw11-package-windows-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase11-logs/package-windows.log b/docs/phase11-logs/package-windows.log new file mode 100644 index 0000000..7bf8a4f --- /dev/null +++ b/docs/phase11-logs/package-windows.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/sw11-package-windows/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase11-logs/reel-final.log b/docs/phase11-logs/reel-final.log new file mode 100644 index 0000000..27d5dc3 --- /dev/null +++ b/docs/phase11-logs/reel-final.log @@ -0,0 +1,11 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +Movie Maker mode enabled, recording movie in 1440×864 @ 30 FPS... +-------------------------------------------------------------------------------- +Done recording movie at path: /tmp/ringborke-animation-final.avi +760 frames at 30 FPS (movie length: 00:00:25:10), recorded in 00:00:23 (108% of real-time speed). +CPU render time: 0.45 seconds (average: 0.59 ms/frame) +GPU render time: 1.48 seconds (average: 1.95 ms/frame) +Encoding time: 1.47 seconds (average: 1.93 ms/frame) +-------------------------------------------------------------------------------- diff --git a/docs/phase11-logs/reel.log b/docs/phase11-logs/reel.log new file mode 100644 index 0000000..be806ff --- /dev/null +++ b/docs/phase11-logs/reel.log @@ -0,0 +1,11 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +Movie Maker mode enabled, recording movie in 1440×864 @ 30 FPS... +-------------------------------------------------------------------------------- +Done recording movie at path: /tmp/ringborke-animation.avi +760 frames at 30 FPS (movie length: 00:00:25:10), recorded in 00:00:23 (108% of real-time speed). +CPU render time: 0.40 seconds (average: 0.52 ms/frame) +GPU render time: 1.41 seconds (average: 1.85 ms/frame) +Encoding time: 1.43 seconds (average: 1.88 ms/frame) +-------------------------------------------------------------------------------- diff --git a/docs/phase11-logs/review.log b/docs/phase11-logs/review.log new file mode 100644 index 0000000..49c28a0 --- /dev/null +++ b/docs/phase11-logs/review.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +RINGBORKE_REVIEW_PASS diff --git a/docs/phase11-logs/rig-test.log b/docs/phase11-logs/rig-test.log new file mode 100644 index 0000000..b3200a9 --- /dev/null +++ b/docs/phase11-logs/rig-test.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RIG_PASS: 33 checks; 0 failures diff --git a/docs/phase11-logs/rules.log b/docs/phase11-logs/rules.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase11-logs/rules.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase11-logs/smoke.log b/docs/phase11-logs/smoke.log new file mode 100644 index 0000000..5de256a --- /dev/null +++ b/docs/phase11-logs/smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 271 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw11-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase11-package-check.json b/docs/phase11-package-check.json new file mode 100644 index 0000000..11250b2 --- /dev/null +++ b/docs/phase11-package-check.json @@ -0,0 +1,29 @@ +{ + "version": "0.11.0", + "packages": [ + { + "platform": "Linux", + "executable": "linux/Saumwacht.x86_64", + "exe_bytes": 333199728, + "archive": "Saumwacht-Linux-x64-0.11.0.zip", + "archive_bytes": 228366955, + "sha256": "7cc8ab4ebf27b1f14fd66bc337a1c01f0b669f98bda3ed47fa7e8c31948e3692", + "exe_sha256": "03a28d9bb67a9de3bd59c25e31ae8e68f8d9623e00a5dd5f015424d72700a4ae", + "crc": "OK", + "archive_sha256_matches": true, + "extracted_sha256_matches": true + }, + { + "platform": "Windows", + "executable": "windows/Saumwacht.exe", + "exe_bytes": 368948800, + "archive": "Saumwacht-Windows-x64-0.11.0.zip", + "archive_bytes": 238281173, + "sha256": "eef9e6136d628a233c25be04bdbd86e57fc32c21f0b0f1168b5c79ef5c0d5da3", + "exe_sha256": "b7538cdab9d4c6ac903d72c156be43f229d5422b791c4a99b71a4c2a4b06321a", + "crc": "OK", + "archive_sha256_matches": true, + "extracted_sha256_matches": true + } + ] +} diff --git a/docs/phase11-package-linux.json b/docs/phase11-package-linux.json new file mode 100644 index 0000000..b250d27 --- /dev/null +++ b/docs/phase11-package-linux.json @@ -0,0 +1,5504 @@ +{ + "checks": 1684, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase11-package-opengl.json b/docs/phase11-package-opengl.json new file mode 100644 index 0000000..19cbe33 --- /dev/null +++ b/docs/phase11-package-opengl.json @@ -0,0 +1,7 @@ +{ + "checks": 128, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase11-package-windows.json b/docs/phase11-package-windows.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase11-package-windows.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase11-rig-verification.json b/docs/phase11-rig-verification.json new file mode 100644 index 0000000..f0dc376 --- /dev/null +++ b/docs/phase11-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 33, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase11-skin-audit.json b/docs/phase11-skin-audit.json new file mode 100644 index 0000000..8a866e9 --- /dev/null +++ b/docs/phase11-skin-audit.json @@ -0,0 +1,20 @@ +{ + "checks": 30, + "failures": [], + "vertices": 59956, + "blended_vertices": 15442, + "blended_percent": 25.76, + "max_weight_sum_error": 2.9802322387695312e-08, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "start", + "stop", + "walk" + ], + "bones": 27 +} diff --git a/docs/phase12-QA.md b/docs/phase12-QA.md new file mode 100644 index 0000000..57ed91c --- /dev/null +++ b/docs/phase12-QA.md @@ -0,0 +1,45 @@ +# Arbeiter · Demo 0.12.0 + +Stand: **22. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. + +| Prüfung | Ergebnis | +| --- | ---: | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Arbeiter: exportierte Geometrie, Gewichte und Clips | 43 bestanden | +| Arbeiter: Godot-Skelett und Arbeitszyklus | 31 bestanden | +| Quellprojekt: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Quellprojekt: Kurzpartie, Assets, Audio, Betrachter und Optionen | 271 bestanden | +| Entpacktes Linux-Paket: Kurzpartie und vier KI-Partien | 271 + 1.665 bestanden | + +Alle genannten automatischen Prüfungen enden ohne fehlgeschlagene Checks. Die vier regulären Duelle enden unverändert bei Welle 20 mit Kern-HP 1.244/1.709, 1.709/1.244, 1.244/1.244 und der Kurzpartie 3.000/3.000. + +## Modell und Animation + +Der Funkenleser besitzt **7.184 Dreiecke, 27 Knochen und zehn Bewegungen**. Von 4.260 Vertices verwenden 888 mehrere Knochengewichte (20,85 %). Alle Gewichte sind normalisiert. Der Arbeitszyklus umfasst Werkzeugkontakt (Kontakt bei 62 %), Aufnehmen, Einfüllen und Rückkehr, dazu Ruhe, Gehen, Treffer und Tod. + +Die Kernprüfung bestätigt Aktivierung, Schadenszustand und Pose-Aufrufe. Die vier KI-Partien verwenden die neue Figur ohne Regeländerung. + +| Reguläres Duell | Letzte Welle | Kern-HP | +| --- | ---: | ---: | +| Wurzelbund → Glutpakt | 20 | 1.244 / 1.709 | +| Glutpakt → Wurzelbund | 20 | 1.709 / 1.244 | +| Wurzelbund → Wurzelbund | 20 | 1.244 / 1.244 | +| Wurzelbund-Spiegel, Kurzpartie | 8 | 3.000 / 3.000 | + +## Nachweise und Wiederholung + +```bash +# Im Quellprojekt saumwacht-godot: +godot --headless --path . res://tests/test_runner.tscn +python3 tools/verify_arbeiter.py +godot --headless --path . res://tools/verify_arbeiter.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +godot --path . res://tools/arbeiter_review.tscn +``` + +[Skin-Audit](phase12-skin-audit.json) · [Skelettprüfung](phase12-rig-verification.json) · [Screenshots](screenshots/phase12/) · [Pakete](phase12-builds.md). + +Tatsächliche Godot-Aufnahmen: [Vorderseite](screenshots/phase12/arbeiter-front.png), [Rückseite](screenshots/phase12/arbeiter-back.png), [Werkzeugkontakt](screenshots/phase12/pose-strike.png), [Aufnehmen](screenshots/phase12/pose-pickup.png), [Einfüllen](screenshots/phase12/pose-deposit.png). + +[Modellbericht](../../docs/phase-12-arbeiter.md) · [Historische Prüfung 0.11](phase11-QA.md). diff --git a/docs/phase12-builds.md b/docs/phase12-builds.md new file mode 100644 index 0000000..a49ae34 --- /dev/null +++ b/docs/phase12-builds.md @@ -0,0 +1,29 @@ +# Demo 0.12.0 · Windows und Linux + +Stand: 22. September 2026. Der Funkenleser ist die zweite Musterfigur mit gewichtetem Skelett: zehn Bewegungen inklusive Werkzeugkontakt, Aufnehmen, Einfüllen und Rückkehr. Die Saumkerne zeigen Aktivierung, ruhigen Betrieb und Schadensreaktion. Enthalten bleiben Ringborke, Glutpakt, Wurzelbund, 8/20 Wellen, Rivalen-KI und die Ruinenlandschaft. + +| System | Paket | Größe | +| --- | --- | ---: | +| Windows | [Saumwacht-Windows-x64-0.12.0.zip](../../dist/Saumwacht-Windows-x64-0.12.0.zip) | 227,4 MiB | +| Linux | [Saumwacht-Linux-x64-0.12.0.zip](../../dist/Saumwacht-Linux-x64-0.12.0.zip) | 218,0 MiB | + +ZIP vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh` oder `Saumwacht.x86_64`. Godot und Blender werden zum Spielen nicht benötigt. Beide Archive enthalten Anleitung, Lizenzen und einen OpenGL-Kompatibilitätsstarter. + +**V → Funkenleser** öffnet die neue Figur mit Bewegungsauswahl, Pause und Zeitleiste. C zeigt die Basis mit Arbeitern und den reagierenden Kristallen. + +## Paketprüfung + +Die Archive bestehen CRC- und SHA-256-Prüfung. Das entpackte Linux-Paket wurde außerhalb des Quellprojekts geprüft: **271** Kurzpartie-/Asset-Checks und **1.665** Bedien- und Partiechecks, keine Fehler. Die vier regulären Duelle enden unverändert bei Welle 20. Ein nativer Windows-Lauf wurde nicht durchgeführt. + +[Prüfbericht](phase12-QA.md) · [Modellbericht](../../docs/phase-12-arbeiter.md). + +## Wiederaufbau + +`python3 tools/build_demo.py` aus `saumwacht-godot` nutzt die offiziellen Godot-4.7.2-Release-Templates. + +## SHA-256 + +```text +09b40beac840207807e4622a0bd26afca537e68e215a64f858fc39c93ad4ec7b Saumwacht-Linux-x64-0.12.0.zip +01cadbcd5e64026d3d51f5a598b1625b99e0d1f6f7ec9feaff9a49df6b7314c6 Saumwacht-Windows-x64-0.12.0.zip +``` diff --git a/docs/phase12-rig-verification.json b/docs/phase12-rig-verification.json new file mode 100644 index 0000000..5d3fb2e --- /dev/null +++ b/docs/phase12-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 40, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase12-skin-audit.json b/docs/phase12-skin-audit.json new file mode 100644 index 0000000..1f55648 --- /dev/null +++ b/docs/phase12-skin-audit.json @@ -0,0 +1,21 @@ +{ + "checks": 43, + "failures": [], + "vertices": 4260, + "blended_vertices": 888, + "blended_percent": 20.85, + "max_weight_sum_error": 2.9802322387695312e-08, + "clips": [ + "death", + "deposit", + "hit", + "idle", + "pickup", + "return", + "start", + "stop", + "strike", + "walk" + ], + "bones": 27 +} diff --git a/docs/phase13-QA.md b/docs/phase13-QA.md new file mode 100644 index 0000000..61d7c29 --- /dev/null +++ b/docs/phase13-QA.md @@ -0,0 +1,28 @@ +# Grafik und Menü · Demo 0.13.0 + +Stand: **22. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. + +| Prüfung | Ergebnis | +| --- | ---: | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Smoke / Assets / Betrachter / Optionen | 271 bestanden | + +Alle Checks ohne Fehler. Matchergebnisse unverändert (1.244/1.709, 1.709/1.244, 1.244/1.244, Kurzpartie 3.000/3.000). + +## Sichtbare Änderungen + +Cineastische Beleuchtung (warmes Key, kühles Fill, Rim), ACES mit angehobenem Kontrast, dezenter Höhennebel. Titelmenü mit großem Titel, gerahmtem Helden, Fraktionskarten und Gold-CTA. HUD-Glaspanels, leuchtende Primäraktionen, überarbeitete Baukarten und Optionsdialog. Leuchtende Team-/Auswahlringe und klarere HP-Balken im Kampf; Glühpoden im Modellbetrachter. + +![Menü](screenshots/phase13/menu.png) · ![Spiel](screenshots/phase13/build.png) + +## Nachweise + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +godot --path . res://tools/ui_review.tscn +``` + +[Modellbericht Grafik](../../docs/phase-13-grafik-und-menu.md) · [Phase 12](phase12-QA.md) · [Pakete](phase13-builds.md). diff --git a/docs/phase13-builds.md b/docs/phase13-builds.md new file mode 100644 index 0000000..bd455d0 --- /dev/null +++ b/docs/phase13-builds.md @@ -0,0 +1,23 @@ +# Demo 0.13.0 · Windows und Linux + +Stand: 22. September 2026. Cineastische Beleuchtung, überarbeitetes Titelmenü und HUD-Glaspanels. Enthalten bleiben Funkenleser, Ringborke, beide Fraktionen und 8/20 Wellen. + +| System | Paket | Größe | +| --- | --- | ---: | +| Windows | [Saumwacht-Windows-x64-0.13.0.zip](../../dist/Saumwacht-Windows-x64-0.13.0.zip) | 227,4 MiB | +| Linux | [Saumwacht-Linux-x64-0.13.0.zip](../../dist/Saumwacht-Linux-x64-0.13.0.zip) | 218,0 MiB | + +ZIP vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh`. Bei Vulkan-Problemen die Kompatibilitätsstarter nutzen. + +## Paketprüfung + +Quellprojekt: 209 + 1.665 + 271 Checks ohne Fehler. Entpacktes Linux-Paket: Smoke-Test bestanden. + +[Prüfbericht](phase13-QA.md) · [Modellbericht](../../docs/phase-13-grafik-und-menu.md). + +## SHA-256 + +```text +7012bfe2f80bc1e92548601cb71706891ea2ada90d5931a02c28ac541e4c0a08 Saumwacht-Linux-x64-0.13.0.zip +c5faeecd2f70db1b125728f2b96d9fc006a06be9bdc14a649d77ec2d6be38fba Saumwacht-Windows-x64-0.13.0.zip +``` diff --git a/docs/phase15-rig-verification.json b/docs/phase15-rig-verification.json new file mode 100644 index 0000000..a9984dc --- /dev/null +++ b/docs/phase15-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 28, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase15-skin-audit.json b/docs/phase15-skin-audit.json new file mode 100644 index 0000000..27c5e88 --- /dev/null +++ b/docs/phase15-skin-audit.json @@ -0,0 +1,18 @@ +{ + "checks": 13, + "failures": [], + "vertices": 4138, + "blended_percent": 17.69, + "bones": 17, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "start", + "stop", + "walk" + ] +} diff --git a/docs/phase16-rig-verification.json b/docs/phase16-rig-verification.json new file mode 100644 index 0000000..a9984dc --- /dev/null +++ b/docs/phase16-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 28, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase16-skin-audit.json b/docs/phase16-skin-audit.json new file mode 100644 index 0000000..6940584 --- /dev/null +++ b/docs/phase16-skin-audit.json @@ -0,0 +1,19 @@ +{ + "checks": 19, + "failures": [], + "vertices": 7322, + "blended_percent": 40.56, + "bones": 17, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "start", + "stop", + "walk" + ], + "note": "Foliage sheets (Leaf/Moss) allowed open; structural parts closed." +} diff --git a/docs/phase17-QA.md b/docs/phase17-QA.md new file mode 100644 index 0000000..b88044e --- /dev/null +++ b/docs/phase17-QA.md @@ -0,0 +1,61 @@ +# Integration und Animationen · Demo 0.14.0 + +Stand: **24. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. Geprüfte Pakete: [Linux und Windows 0.14.0](phase17-builds.md). + +| Prüfung | Ergebnis | +| --- | ---: | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Eigene Fähigkeit / empfangene Heilung / Basalt-Schutzhaltung, Pause, 1×/2× | 33 bestanden | +| Ringborke / Basaltbastion / Quellgeflecht: bestehende Rig-Prüfungen | 33 / 28 / 28 bestanden | +| Arbeiter: Rig, Clips, Zyklus und Kontakte bei 30/60/144 FPS | 40 bestanden | +| Blatt-/Moos-/Blütenrückseiten, Forward+ und OpenGL | jeweils 13 bestanden | +| Quellprojekt: Fähigkeiten, Bedienung und vier KI-Partien | 1.665 bestanden | +| Quellprojekt: erweiterte Paket-/Modellprüfung | 398 bestanden | +| Entpacktes Linux-Release mit Vulkan: Modelle, UI, Acht-Wellen-Partie und Screenshots | 408 bestanden | +| Entpacktes Windows-PCK unter Linux: Modelle, UI und Acht-Wellen-Partie | 398 bestanden | +| Entpacktes Windows-PCK unter Linux: vier KI-Partien, davon drei über 20 Wellen | 1.665 bestanden | +| Entpackter Linux-Kompatibilitätsstarter mit OpenGL: Bedienprüfung | 128 bestanden | +| Beide ZIPs und enthaltene Programme | CRC / SHA-256 / README-Version / Schriftlizenz bestanden | +| Nativer Windows-Lauf | Nicht durchgeführt | + +Alle oben genannten Prüfungen enden ohne fehlgeschlagene Checks. Die Pakete liefen aus `/tmp/saumwacht-014-package-check`, mit getrennten temporären Benutzerordnern. Die Release-Laufzeitprotokolle enthalten keine Skript-, Shader- oder Laufzeitfehler. Die Exportprotokolle melden den in der Sandbox nicht verfügbaren Editor-TCP-Port; beide Exporte selbst endeten erfolgreich. + +## Was gezielt abgesichert ist + +Die Basaltbastion zeigt ihre Schutzhaltung erst beim ersten Kampfschritt und wiederholt sie weder nach Fremdheilung noch nach Ablauf des stärkeren Schutzes. Die bestehenden Reduktionswerte bleiben gleich. Quellgeflecht heilt weiterhin 80 HP je Ziel; nur der Ausführende startet seine eigene Fähigkeitsbewegung. Empfänger behalten den sichtbaren Heilpuls. Eine spätere echte Selbstheilung der Ringborke startet weiterhin ihre eigene Animation. + +Beim Arbeiter zählt jede der neun Kombinationen aus Bildrate und Startversatz exakt drei Kontakte in drei vollständigen Zyklen. Zusätzliches Abfragen bei `delta = 0` erzeugt keinen Kontakt. Die reale Paketroutine prüft einen vollständigen Arbeitszyklus samt genau einem Werkzeugkontakt. + +Die Materialprüfung rendert die importierten Blatt-, Moos- und Blütenmaterialien von vorn und hinten und misst die Pixelhelligkeit in beiden Renderern. Die Paketprüfung verlangt die konkrete Manifestwahl für Ringborke, Funkenleser, Basaltbastion und Quellgeflecht sowie gebundene Skin-Meshes, erwartete Knochenzahlen, Clipspuren und tatsächlich bewegte Knochen. Eine zweite Instanz muss ihre eigene Pose behalten. + +## Partien + +| Reguläres Duell | Letzte Welle | Kern-HP | +| --- | ---: | --- | +| Wurzelbund → Glutpakt | 20 | 1.244 / 1.709 | +| Glutpakt → Wurzelbund | 20 | 1.709 / 1.244 | +| Wurzelbund → Wurzelbund | 20 | 1.244 / 1.244 | +| Wurzelbund-Spiegel, Kurzpartie | 8 | 3.000 / 3.000 | + +Die Quellprojekt- und Windows-PCK-Läufe liefern dieselben bisherigen Ergebnisse. Die separate Acht-Wellen-Smokepartie gegen die Lern-KI endet mit 3.000 / 1.035 Kern-HP. Keine Änderung an Preisen, Einkommen, Schadenswerten oder Heilreichweiten. + +## Nachweise und Wiederholung + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . res://tools/verify_ability_events.tscn +godot --headless --path . res://tools/verify_arbeiter.tscn +godot --path . res://tools/verify_material_sides.tscn +godot --path . --rendering-method gl_compatibility res://tools/verify_material_sides.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +python3 tools/build_demo.py --check-only +``` + +Die Grafikprüfung benötigt ein Display. Für isolierte Prüfläufe `XDG_DATA_HOME` und `XDG_CONFIG_HOME` auf temporäre Verzeichnisse setzen. Die entpackten Programme unterstützen dieselben `-- --smoke-test` / `-- --faction-test` / `-- --faction-test --ui-only` Argumente; beim Windows-PCK unter Linux zusätzlich `godot --main-pack /absoluter/Pfad/Saumwacht.exe` verwenden. + +[Release-Ergebnisse](phase17-release-verification.json) · [Fähigkeitsereignisse](phase17-ability-verification.json) · [Arbeiter](phase17-worker-verification.json) · [Forward+](phase17-material-forward.json) · [OpenGL](phase17-material-opengl.json) · [Quellprojekt-Partien](phase17-faction-verification.json) · [Windows-PCK-Partien](phase17-package-windows.json) · [OpenGL-Paket](phase17-package-opengl.json) · [Paketintegrität](phase17-package-check.json) · [Protokolle](phase17-logs/). + +Aufnahmen direkt aus der entpackten Linux-Demo: [Basaltbastion](screenshots/phase17/package-model-g04.png), [Quellgeflecht](screenshots/phase17/package-model-w10.png), [Funkenleser](screenshots/phase17/package-model-worker.png), [Bauen](screenshots/phase17/package-build.png), [Kampf](screenshots/phase17/package-combat.png). + +Diese Phase verbessert Funktions- und Exportzuverlässigkeit. Sie ersetzt weder die noch ausstehende künstlerische Überarbeitung der übrigen Figuren noch menschliche Balance- und Bedienungstests. [Projektstand und nächste Arbeiten](../../docs/phase-17-integration-und-demo.md). diff --git a/docs/phase17-ability-verification.json b/docs/phase17-ability-verification.json new file mode 100644 index 0000000..f0dc376 --- /dev/null +++ b/docs/phase17-ability-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 33, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase17-builds.md b/docs/phase17-builds.md new file mode 100644 index 0000000..4ce42fb --- /dev/null +++ b/docs/phase17-builds.md @@ -0,0 +1,36 @@ +# Demo 0.14.0 · Linux und Windows + +Stand: 24. September 2026. Fähigkeitsauslöser, Werkzeugkontakte und zweiseitige Blattmaterialien sind korrigiert. Alle vier Skelettfiguren werden im Paket auf ihre tatsächlich geladenen Modelle und Animationen geprüft. + +| System | Paket | Größe | +| --- | --- | ---: | +| Linux | [Saumwacht-Linux-x64-0.14.0.zip](../../dist/Saumwacht-Linux-x64-0.14.0.zip) | 261.3 MiB | +| Windows | [Saumwacht-Windows-x64-0.14.0.zip](../../dist/Saumwacht-Windows-x64-0.14.0.zip) | 270.8 MiB | + +ZIP vollständig entpacken. Linux: `Spielen.sh`; Windows: `Saumwacht.exe`. Bei Vulkan-Problemen `Kompatibilitaet.sh` bzw. `Kompatibilitaet.bat` starten. Beide Pakete enthalten die Spieldaten; Godot und Blender sind zum Spielen nicht erforderlich. + +## Nachweis + +Die Archive wurden mit CRC geprüft, außerhalb des Quellprojekts entpackt und die Programm-Hashes mit dem Buildmanifest verglichen. README-Version und Schriftlizenz sind enthalten. Die Linux-Demo wurde mit ihrem eigenen offiziellen Release-Programm unter Vulkan und OpenGL geprüft. Das Windows-PCK wurde mit Godot unter Linux geprüft; **ein nativer Windows-Lauf steht aus**. + +Projekt, ZIP-Dateiname, Buildmanifest und Export-Presets verwenden 0.14.0. Die Option `application/modify_resources=false` bleibt bestehen; native Windows-PE-Versionsressourcen werden nicht umgeschrieben. + +[QA mit Ergebnissen](phase17-QA.md) · [Paketintegrität](phase17-package-check.json) · [Buildmanifest](../../dist/build-manifest.json) · [Projektstand und nächste Arbeiten](../../docs/phase-17-integration-und-demo.md). + +## SHA-256 + +```text +3694574cd6212e8ac5c05cfdd9d9ed52ac9f313fa0417f4de11ae3be9361a914 Saumwacht-Linux-x64-0.14.0.zip +b06b3e98ce19cfc4ce2e500014c4bbac806efac20406e29ab6a3182fb2c61c8d Saumwacht-Windows-x64-0.14.0.zip +``` + +## Wiederholen + +Im Ordner `saumwacht-godot`: + +```bash +python3 tools/build_demo.py --check-only +python3 tools/build_demo.py +``` + +Die Vorprüfung kontrolliert Laufzeitmanifeste, Ressourcen, Skelettmodell-Hashes und Versionsgleichheit. Ein exportierter Stand wird anschließend mit `-- --smoke-test` und `-- --faction-test` geprüft; der Builder allein bescheinigt keine erfolgreiche Spielprüfung. diff --git a/docs/phase17-faction-verification.json b/docs/phase17-faction-verification.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase17-faction-verification.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase17-logs/builds.log b/docs/phase17-logs/builds.log new file mode 100644 index 0000000..e6a866b --- /dev/null +++ b/docs/phase17-logs/builds.log @@ -0,0 +1,3 @@ +RELEASE_INPUTS_PASS: Version 0.14.0, 8 Manifeste, vier Skelettmodelle. +Linux: Saumwacht-Linux-x64-0.14.0.zip (261.3 MiB) +Windows: Saumwacht-Windows-x64-0.14.0.zip (270.8 MiB) diff --git a/docs/phase17-logs/faction.log b/docs/phase17-logs/faction.log new file mode 100644 index 0000000..7c5b3a4 --- /dev/null +++ b/docs/phase17-logs/faction.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/saumwacht-phase17/data/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase17-logs/material-sides-opengl.log b/docs/phase17-logs/material-sides-opengl.log new file mode 100644 index 0000000..9c75392 --- /dev/null +++ b/docs/phase17-logs/material-sides-opengl.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +MATERIAL_PASS: 13 checks; 0 failures diff --git a/docs/phase17-logs/material-sides.log b/docs/phase17-logs/material-sides.log new file mode 100644 index 0000000..c53de26 --- /dev/null +++ b/docs/phase17-logs/material-sides.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +MATERIAL_PASS: 13 checks; 0 failures diff --git a/docs/phase17-logs/package-linux-models.log b/docs/phase17-logs/package-linux-models.log new file mode 100644 index 0000000..eec7650 --- /dev/null +++ b/docs/phase17-logs/package-linux-models.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +{"manifests":{"res://assets/phase11_manifest.json":true,"res://assets/phase12_manifest.json":true,"res://assets/phase15_manifest.json":true,"res://assets/phase16_manifest.json":true,"res://assets/phase3_manifest.json":true,"res://assets/phase4_manifest.json":true},"models":{"g04":{"clips":9,"path":"res://assets/characters/basaltbastion.glb"},"w04":{"clips":9,"path":"res://assets/characters/ringborke.glb"},"w10":{"clips":9,"path":"res://assets/characters/quellgeflecht.glb"},"worker":{"clips":10,"path":"res://assets/characters/arbeiter.glb"}},"version":"0.14.0"} diff --git a/docs/phase17-logs/package-linux-visual.log b/docs/phase17-logs/package-linux-visual.log new file mode 100644 index 0000000..bad2d7e --- /dev/null +++ b/docs/phase17-logs/package-linux-visual.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 408 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-014-linux/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase17-logs/package-opengl-ui.log b/docs/phase17-logs/package-opengl-ui.log new file mode 100644 index 0000000..6810070 --- /dev/null +++ b/docs/phase17-logs/package-opengl-ui.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /tmp/saumwacht-014-opengl/data/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase17-logs/package-windows-faction.log b/docs/phase17-logs/package-windows-faction.log new file mode 100644 index 0000000..9c3eee0 --- /dev/null +++ b/docs/phase17-logs/package-windows-faction.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /tmp/saumwacht-014-windows/data/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json diff --git a/docs/phase17-logs/package-windows-models.log b/docs/phase17-logs/package-windows-models.log new file mode 100644 index 0000000..eec7650 --- /dev/null +++ b/docs/phase17-logs/package-windows-models.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +{"manifests":{"res://assets/phase11_manifest.json":true,"res://assets/phase12_manifest.json":true,"res://assets/phase15_manifest.json":true,"res://assets/phase16_manifest.json":true,"res://assets/phase3_manifest.json":true,"res://assets/phase4_manifest.json":true},"models":{"g04":{"clips":9,"path":"res://assets/characters/basaltbastion.glb"},"w04":{"clips":9,"path":"res://assets/characters/ringborke.glb"},"w10":{"clips":9,"path":"res://assets/characters/quellgeflecht.glb"},"worker":{"clips":10,"path":"res://assets/characters/arbeiter.glb"}},"version":"0.14.0"} diff --git a/docs/phase17-logs/package-windows-smoke.log b/docs/phase17-logs/package-windows-smoke.log new file mode 100644 index 0000000..9d0ac77 --- /dev/null +++ b/docs/phase17-logs/package-windows-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 398 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-014-windows-smoke/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase17-logs/previous-package.log b/docs/phase17-logs/previous-package.log new file mode 100644 index 0000000..01cd45a --- /dev/null +++ b/docs/phase17-logs/previous-package.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +{"manifests":{"res://assets/phase11_manifest.json":true,"res://assets/phase12_manifest.json":true,"res://assets/phase15_manifest.json":true,"res://assets/phase16_manifest.json":true,"res://assets/phase3_manifest.json":true,"res://assets/phase4_manifest.json":true},"models":{"g04":{"clips":9,"path":"res://assets/characters/basaltbastion.glb"},"w04":{"clips":9,"path":"res://assets/characters/ringborke.glb"},"w10":{"clips":9,"path":"res://assets/characters/quellgeflecht.glb"},"worker":{"clips":10,"path":"res://assets/characters/arbeiter.glb"}},"resource_root":"","version":"0.11.0"} diff --git a/docs/phase17-logs/quell-review.log b/docs/phase17-logs/quell-review.log new file mode 100644 index 0000000..9665c92 --- /dev/null +++ b/docs/phase17-logs/quell-review.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +QUELL_MODEL: w10 caption=Quellgeflecht path=res://assets/characters/quellgeflecht.glb tris=14276.0 +QUELL_REVIEW_PASS diff --git a/docs/phase17-logs/source-smoke.log b/docs/phase17-logs/source-smoke.log new file mode 100644 index 0000000..f0c3714 --- /dev/null +++ b/docs/phase17-logs/source-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 398 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase17-smoke/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase17-logs/worker-rig.log b/docs/phase17-logs/worker-rig.log new file mode 100644 index 0000000..ea63cd6 --- /dev/null +++ b/docs/phase17-logs/worker-rig.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RIG_PASS: 40 checks; 0 failures diff --git a/docs/phase17-material-forward.json b/docs/phase17-material-forward.json new file mode 100644 index 0000000..95ba788 --- /dev/null +++ b/docs/phase17-material-forward.json @@ -0,0 +1,19 @@ +{ + "checks": 13, + "failures": [], + "materials": { + "QG_Leaf": { + "back_luminance": 0.992156863212585, + "front_luminance": 0.988235294818878 + }, + "QG_Moss": { + "back_luminance": 0.992156863212585, + "front_luminance": 0.988235294818878 + }, + "QG_Petal": { + "back_luminance": 0.992156863212585, + "front_luminance": 0.988235294818878 + } + }, + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase17-material-opengl.json b/docs/phase17-material-opengl.json new file mode 100644 index 0000000..2f04322 --- /dev/null +++ b/docs/phase17-material-opengl.json @@ -0,0 +1,19 @@ +{ + "checks": 13, + "failures": [], + "materials": { + "QG_Leaf": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + }, + "QG_Moss": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + }, + "QG_Petal": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + } + }, + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase17-material-verification.json b/docs/phase17-material-verification.json new file mode 100644 index 0000000..2f04322 --- /dev/null +++ b/docs/phase17-material-verification.json @@ -0,0 +1,19 @@ +{ + "checks": 13, + "failures": [], + "materials": { + "QG_Leaf": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + }, + "QG_Moss": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + }, + "QG_Petal": { + "back_luminance": 0.984313726425171, + "front_luminance": 0.972549021244049 + } + }, + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase17-package-check.json b/docs/phase17-package-check.json new file mode 100644 index 0000000..c9737d8 --- /dev/null +++ b/docs/phase17-package-check.json @@ -0,0 +1,25 @@ +{ + "version": "0.14.0", + "packages": [ + { + "platform": "Linux", + "archive": "Saumwacht-Linux-x64-0.14.0.zip", + "sha256": "3694574cd6212e8ac5c05cfdd9d9ed52ac9f313fa0417f4de11ae3be9361a914", + "executable_sha256": "f036ff48c11417f8013100d2fccabcd82a7ba95536b349749fdf06724399d761", + "crc": "passed", + "version_in_readme": "0.14.0", + "font_license": true, + "extracted_to": "/tmp/saumwacht-014-package-check/Saumwacht-Linux" + }, + { + "platform": "Windows", + "archive": "Saumwacht-Windows-x64-0.14.0.zip", + "sha256": "b06b3e98ce19cfc4ce2e500014c4bbac806efac20406e29ab6a3182fb2c61c8d", + "executable_sha256": "d23e847daba254f340d9840873149b7d1ff16441d1939cf2034c19e617dd38a7", + "crc": "passed", + "version_in_readme": "0.14.0", + "font_license": true, + "extracted_to": "/tmp/saumwacht-014-package-check/Saumwacht-Windows" + } + ] +} diff --git a/docs/phase17-package-opengl.json b/docs/phase17-package-opengl.json new file mode 100644 index 0000000..19cbe33 --- /dev/null +++ b/docs/phase17-package-opengl.json @@ -0,0 +1,7 @@ +{ + "checks": 128, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase17-package-windows.json b/docs/phase17-package-windows.json new file mode 100644 index 0000000..27c44b5 --- /dev/null +++ b/docs/phase17-package-windows.json @@ -0,0 +1,5504 @@ +{ + "checks": 1665, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase17-release-verification.json b/docs/phase17-release-verification.json new file mode 100644 index 0000000..3b9e617 --- /dev/null +++ b/docs/phase17-release-verification.json @@ -0,0 +1,31 @@ +{ + "version": "0.14.0", + "runs": { + "source_smoke": { + "checks": 398, + "failures": [], + "log": "phase17-logs/source-smoke.log" + }, + "linux_vulkan_smoke": { + "checks": 408, + "failures": [], + "log": "phase17-logs/package-linux-visual.log" + }, + "windows_pck_smoke": { + "checks": 398, + "failures": [], + "log": "phase17-logs/package-windows-smoke.log" + }, + "windows_pck_faction": { + "checks": 1665, + "failures": [], + "log": "phase17-logs/package-windows-faction.log" + }, + "linux_opengl_ui": { + "checks": 128, + "failures": [], + "log": "phase17-logs/package-opengl-ui.log" + } + }, + "native_windows_test": false +} diff --git a/docs/phase17-worker-verification.json b/docs/phase17-worker-verification.json new file mode 100644 index 0000000..5d3fb2e --- /dev/null +++ b/docs/phase17-worker-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 40, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase18-QA.md b/docs/phase18-QA.md new file mode 100644 index 0000000..c1190d2 --- /dev/null +++ b/docs/phase18-QA.md @@ -0,0 +1,40 @@ +# Phase 18 · Funkenlanze g05 · QA + +Stand: 24. September 2026. Fünfte Musterfigur mit gewichtetem Skelett — Fernkampf mit Kristall-Lanzenbüchse. + +## Ergebnis + +| Prüfung | Ergebnis | Beweis | +| --- | ---: | --- | +| GLB-Geometrie, Gewichte, Clips | 30 bestanden | [phase18-skin-audit.json](phase18-skin-audit.json) | +| Godot-Skelett und Kampfanbindung | 35 bestanden | [phase18-rig-verification.json](phase18-rig-verification.json) | +| Wirtschaft, Kampf, Lebenszyklus | 209 bestanden | `tests/test_runner.tscn` | +| Fähigkeiten, Bedienung, vier KI-Partien | 1.665 bestanden | `--faction-test` | +| Smoke / Assets | 424 bestanden | `--smoke-test` | +| Review-Captures (Titel/ID geprüft) | Funkenlanze G05 · 24036 Tri · 26 Knochen | [screenshots/phase18](screenshots/phase18) | + +## Gezielte Anbindung + +- `attack_cycle` `["attack_a","attack_b","attack_a","ability"]` — vierter Treffer spielt den geladenen Schuss. +- Schusskontakt exakt bei `0,90 s`; Verschluss gleitet danach, Kristall dreht beim Aufladen. +- Hände bleiben per analytischer Zwei-Knochen-IK an Griff und Stützpunkt (max. Fehler ~3·10⁻⁷). +- Rüstplatten einstarr gewichtet; durchgehende Gliedmaßenkerne tragen die Gelenkzonen (9,94 % Blended Vertices). +- Materialien `FL_*`; `FL_Ember`/`FL_Crystal` als `StandardMaterial3D.duplicate()` (Emission). + +## Befehle + +```bash +ALSOFT_DRIVERS=null blender -b --python-exit-code 1 --python assets-source/phase18/build_funkenlanze.py +godot --headless --editor --import +python3 tools/verify_funkenlanze.py +godot --headless --path . res://tools/verify_funken.tscn +godot --path . res://tools/funken_review.tscn +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +``` + +## Offen + +- Nativer Windows-Lauf und menschliche Balance-/Bedienungstests (unverändert aus Phase 17). +- Demo-Rebuild mit Funkenlanze im Paket (`python3 tools/build_demo.py`), sobald eine neue Demo-Version fällig ist. diff --git a/docs/phase18-rig-verification.json b/docs/phase18-rig-verification.json new file mode 100644 index 0000000..c1057df --- /dev/null +++ b/docs/phase18-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 35, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase18-skin-audit.json b/docs/phase18-skin-audit.json new file mode 100644 index 0000000..f5a328d --- /dev/null +++ b/docs/phase18-skin-audit.json @@ -0,0 +1,20 @@ +{ + "checks": 30, + "failures": [], + "vertices": 25101, + "blended_vertices": 2496, + "blended_percent": 9.94, + "max_weight_sum_error": 2.9802322387695312e-08, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "start", + "stop", + "walk" + ], + "bones": 26 +} diff --git a/docs/phase19-QA.md b/docs/phase19-QA.md new file mode 100644 index 0000000..30699ef --- /dev/null +++ b/docs/phase19-QA.md @@ -0,0 +1,56 @@ +# Phase 19 · Glasballiste g06 · QA + +Stand: 27. September 2026. Sechste Figur mit gewichtetem Skelett — kopfloser Ballisten-Läufer mit Kristallbogen, Aufwertung der Funkenlanze. + +## Ergebnis + +| Prüfung | Ergebnis | Beweis | +| --- | ---: | --- | +| GLB-Geometrie, Gewichte, Clips | 30 bestanden | [phase19-skin-audit.json](phase19-skin-audit.json) | +| Godot-Skelett, Fußkontakt, Schussablauf, Kampfanbindung | 44 bestanden | [phase19-rig-verification.json](phase19-rig-verification.json) | +| Wirtschaft, Kampf, Lebenszyklus | 209 bestanden | [test-runner.log](phase19-logs/test-runner.log) | +| Fähigkeitsauslöser | 33 bestanden | [ability-events.log](phase19-logs/ability-events.log) | +| Fähigkeiten, Bedienung, vier KI-Partien | 1.665 bestanden | [faction-test.log](phase19-logs/faction-test.log) | +| Smoke / Assets | 450 bestanden | [smoke-test.log](phase19-logs/smoke-test.log) | +| Release-Eingaben (Version, Manifeste, GLB-Hashes) | bestanden | [release-check.log](phase19-logs/release-check.log) | +| Betrachter-Aufnahmen (Titel/ID geprüft) | Glasballiste G06 · 15.784 Dreiecke · 20 Knochen | [screenshots/phase19](screenshots/phase19) | +| Spielkamera (Bau, Nah, Kampf) | zwei aufgewertete Glasballisten | `field-*.png` | + +Die vier KI-Partien enden mit denselben Kernwerten wie in Phase 18; das Modell ändert keine Spielwerte. + +## Überarbeitung gegenüber dem ersten Phase-19-Stand + +Der erste Entwurf vom 24. September bestand die Funktionsprüfungen, wich aber sichtbar vom Konzept ab: ein weißer, humanoider Glasrumpf mit Ladearmen, blasse Bögen und ein schlichter schwarzer Kasten als Rückansicht. Nach der [Qualitätsvorgabe](../../docs/engine-pruefung-2026-09-19.md) zählen Form, Material und Lesbarkeit, nicht bestandene Funktionstests. Die Figur ist deshalb neu aufgebaut: Basaltchassis, Messingrahmen, große facettierte Orangekristall-Bögen, glühende Kristallschiene, Kurbelräder, Fachwerk-Heckgehäuse und digitigrade Beine mit Krallenfüßen, wie im Konzeptbild. Der erste Stand liegt unter `assets-source/phase19/v1-humanoid/`. + +## Gezielte Anbindung + +- `attack_cycle` `["attack_a","attack_b","attack_a","ability"]`. Jeder 4. Treffer spielt den Panzerbrecherschuss. +- Ruhelage ist gespannt und geladen. Auslösung genau bei `0,90 s`: Sehne schnellt vor, Bögen federn nach vorn, Bolzen verlässt die Schiene (ausgeblendet bis `1,02 s`), dann Nachladen über die Kurbel bis `1,24 s`. Bei `1,30 s` stimmt die Pose wieder mit dem Clipbeginn überein. +- Füße sind per analytischer Zwei-Knochen-IK gepflanzt und als FK bei 30 Hz eingebettet. Ein Laufzyklus legt **0,52 m** zurück, wie `SkeletalFigure` rechnet; gepflanzte Füße rutschen messbar nicht (Fehler < 10⁻⁷ m pro Bild). Maximaler Beinkontaktfehler 4,6 · 10⁻⁷ m. +- Tiefster Punkt des verformten Meshs in allen neun Clips: +1 mm über dem Boden. +- Panzerteile sind starr gewichtet. Gelenkmanschetten, Hydraulikschläuche, die sich über ihre Länge biegenden Kristallbögen und die Sehne tragen die Mischgewichte (11,18 %). +- Der Turmknochen heißt `Spine`, damit die vorhandene Trefferüberlagerung greift. Der kopflose Läufer hat keine `Head`-/Arm-Knochen; die Fähigkeitsüberlagerung bleibt dadurch wirkungslos, die Fähigkeit selbst spielt im Angriffszyklus. +- Materialien `GB_*`. `GB_Crystal` und `GB_Ember` werden als `StandardMaterial3D.duplicate()` (Emission) übernommen, die übrigen nutzen den gemeinsamen Oberflächenshader. + +## Befehle + +```bash +ALSOFT_DRIVERS=null blender -b --python-exit-code 1 --python assets-source/phase19/build_glasballiste.py +godot --headless --editor --import +python3 tools/verify_glasballiste.py +godot --headless --path . res://tools/verify_glass.tscn +godot --path . res://tools/glass_review.tscn +godot --path . res://tools/glass_field_review.tscn +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . -- --faction-test +godot --headless --path . -- --smoke-test +python3 tools/build_demo.py --check-only +``` + +`glass_field_review` gibt nur für die Aufnahme zusätzliches Gold aus, um zwei Funkenlanzen aufzuwerten; Balancewerte bleiben unverändert. + +## Offen + +- Nativer Windows-Lauf und menschliche Balance-/Bedienungstests (unverändert aus Phase 17). +- Demo-Rebuild mit Funkenlanze und Glasballiste im Paket (`python3 tools/build_demo.py`), sobald eine neue Demo-Version fällig ist. Die Release-Eingaben sind geprüft. +- Die Glasballiste nutzt Einheitsmaterialien mit Flächen- und Facettenfarben, keine eigenen Texturen. Für Nahansichten wären gebackene Kanten- und Rauheitsdetails der nächste Schritt. diff --git a/docs/phase19-logs/ability-events.log b/docs/phase19-logs/ability-events.log new file mode 100644 index 0000000..6659999 --- /dev/null +++ b/docs/phase19-logs/ability-events.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ABILITY_EVENT_PASS: 33 checks; 0 failures +EXIT 0 diff --git a/docs/phase19-logs/faction-test.log b/docs/phase19-logs/faction-test.log new file mode 100644 index 0000000..38324ec --- /dev/null +++ b/docs/phase19-logs/faction-test.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json +EXIT 0 diff --git a/docs/phase19-logs/release-check.log b/docs/phase19-logs/release-check.log new file mode 100644 index 0000000..550d500 --- /dev/null +++ b/docs/phase19-logs/release-check.log @@ -0,0 +1 @@ +RELEASE_INPUTS_PASS: Version 0.14.0, 10 Manifeste, 6 Skelettmodelle. diff --git a/docs/phase19-logs/rig-verification.log b/docs/phase19-logs/rig-verification.log new file mode 100644 index 0000000..a95fe3d --- /dev/null +++ b/docs/phase19-logs/rig-verification.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RIG_PASS: 44 checks; 0 failures diff --git a/docs/phase19-logs/skin-audit.log b/docs/phase19-logs/skin-audit.log new file mode 100644 index 0000000..f8b6b1b --- /dev/null +++ b/docs/phase19-logs/skin-audit.log @@ -0,0 +1 @@ +{'checks': 30, 'failures': [], 'vertices': 20501, 'blended_vertices': 2292, 'blended_percent': 11.18, 'max_weight_sum_error': 2.9802322387695312e-08, 'clips': ['ability', 'attack_a', 'attack_b', 'death', 'hit', 'idle', 'start', 'stop', 'walk'], 'bones': 20} diff --git a/docs/phase19-logs/smoke-test.log b/docs/phase19-logs/smoke-test.log new file mode 100644 index 0000000..8fcdbe3 --- /dev/null +++ b/docs/phase19-logs/smoke-test.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 450 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke +EXIT 0 diff --git a/docs/phase19-logs/test-runner.log b/docs/phase19-logs/test-runner.log new file mode 100644 index 0000000..ac5e7b6 --- /dev/null +++ b/docs/phase19-logs/test-runner.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. +EXIT 0 diff --git a/docs/phase19-rig-verification.json b/docs/phase19-rig-verification.json new file mode 100644 index 0000000..b3db9d2 --- /dev/null +++ b/docs/phase19-rig-verification.json @@ -0,0 +1,4 @@ +{ + "checks": 44, + "failures": [] +} \ No newline at end of file diff --git a/docs/phase19-skin-audit.json b/docs/phase19-skin-audit.json new file mode 100644 index 0000000..2cbe2ac --- /dev/null +++ b/docs/phase19-skin-audit.json @@ -0,0 +1,20 @@ +{ + "checks": 30, + "failures": [], + "vertices": 20501, + "blended_vertices": 2292, + "blended_percent": 11.18, + "max_weight_sum_error": 2.9802322387695312e-08, + "clips": [ + "ability", + "attack_a", + "attack_b", + "death", + "hit", + "idle", + "start", + "stop", + "walk" + ], + "bones": 20 +} diff --git a/docs/phase20-QA.md b/docs/phase20-QA.md new file mode 100644 index 0000000..7a7b776 --- /dev/null +++ b/docs/phase20-QA.md @@ -0,0 +1,59 @@ +# Phase 20A · Hauptmenü, Bundauswahl und visuelle Identität · QA + +Stand: 27. September 2026. Testumgebung: Fedora Linux 44 (KDE Plasma, XWayland/X11), AMD Ryzen 5 5600X, NVIDIA GeForce RTX 5060 Ti (Vulkan 1.4.351), Godot 4.7.2 (Fedora-Build für das Quellprojekt, offizielles Release-Programm für das Linux-Paket). Die Messwerte gelten nur für diese Umgebung. + +## Automatisierte Prüfungen + +| Prüfung | Ergebnis | Beleg | +| --- | ---: | --- | +| Menüabnahme: Bundwahl per Maus und Tastatur, alle Partieoptionen, Esc, Eingabeschutz, Bühnenisolation, Start, Rückkehr, Neustart, Ergebnisbildschirm, reduzierte Bewegung, 1280×720 / 1920×1080 / Größenänderung | 68 bestanden (je Start in 1280×720 und 1920×1080) | [verify-menu-1280x720.log](phase20-logs/verify-menu-1280x720.log), [verify-menu-1920x1080.log](phase20-logs/verify-menu-1920x1080.log), [phase20-menu-verification.json](phase20-menu-verification.json) | +| Wirtschaft, Kampf, Lebenszyklus | 209 bestanden | [test-runner.log](phase20-logs/test-runner.log) | +| Fähigkeitsauslöser | 33 bestanden | [ability-events.log](phase20-logs/ability-events.log) | +| Glasballiste-Rig | 44 bestanden | [verify-glass.log](phase20-logs/verify-glass.log) | +| Smoke / Assets / Bedienung (Quellprojekt) | 463 bestanden | [smoke-test.log](phase20-logs/smoke-test.log) | +| Expedition, drei KI-Partien | 206 bestanden | [expedition-test.log](phase20-logs/expedition-test.log) | +| Fähigkeiten, Bedienung, vier KI-Partien | 1.665 bestanden | [faction-test.log](phase20-logs/faction-test.log) | +| Bedienung mit Grafik, inkl. Mindestfenster 1152×720 (`--faction-test --ui-only`) | 128 bestanden | [faction-ui-graphical.log](phase20-logs/faction-ui-graphical.log) | +| Release-Vorprüfung | 0.15.0 · 11 Manifeste · 6 Skelettmodelle | `python3 tools/build_demo.py --check-only` | +| Linux-Paket, Vulkan, 1920×1080 | 473 bestanden | [package-linux-vulkan-smoke.log](phase20-logs/package-linux-vulkan-smoke.log) | +| Linux-Paket, OpenGL, 1280×720 | 473 bestanden | [package-linux-opengl-smoke.log](phase20-logs/package-linux-opengl-smoke.log) | +| Linux-Paket, vier KI-Partien | 1.665 bestanden | [package-linux-faction.log](phase20-logs/package-linux-faction.log) | +| Windows-Spieldaten (mit Godot unter Linux) | Smoke 463, Fraktion 1.665 bestanden | [package-windows-smoke.log](phase20-logs/package-windows-smoke.log), [package-windows-faction.log](phase20-logs/package-windows-faction.log) | +| Archive | CRC fehlerfrei, Programm-Hashes = Buildmanifest, LIESMICH 0.15.0, drei Schriftlizenzen | [phase20-package-check.json](phase20-package-check.json) | + +Die KI-Partien enden mit denselben Kernwerten wie vor der Phase (Fraktion: [1244, 1709] · [1709, 1244] · [1244, 1244] · [3000, 3000]; Smoke-Partie [3000, 1035]). Wirtschaft, Kampf, KI und Fähigkeiten sind unverändert. + +### Offen angepasste Tests + +- **Neu:** `tools/verify_menu.gd` sowie 13 Paket-Smoke-Prüfungen (450 → 463): sieben Menügrafiken, drei Menüschriften, das Menü-Diorama und das Bühnen-Manifest (vorhanden, gültig). +- **Unverändert:** Die bisherigen Prüfungen nutzen `hud._overlay_action`, `_faction_pickers`, `_mode_picker` und `_overlay_title` weiter. Diese Namen verweisen jetzt auf die neuen Bauteile mit derselben `select()`-/`item_selected`-Schnittstelle. Erwartungswerte wurden nicht geändert. +- In `verify_menu.gd` wurden zwei eigene Prüfungen während der Entwicklung korrigiert: Klicks scrollen das Einstellungspanel erst in Sicht, und die Partieprüfung berücksichtigt die regulär aufgestellte Rivalenformation. + +## Laufzeit und Ladezeit + +`tools/menu_benchmark.tscn`, VSync aus, 2,5 s Aufwärmen, 6 s Messung. Vorher = Phase-13-Menü mit gerenderter Arena dahinter. + +| | Bild (Mittel / p95) | GPU | Render-CPU | Draw Calls | Grafikspeicher | erstes Bild | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| Menü vorher 1280×720 | 2,15 / 2,87 ms | 2,10 ms | 0,36 ms | 677 | 554 MB | 746 ms | +| **Menü nachher 1280×720** | **1,82 / 2,42 ms** | **1,75 ms** | **0,27 ms** | **397** | **917 MB** | **1.243 ms** | +| Menü vorher 1920×1080 | 3,42 / 4,20 ms | 3,33 ms | 0,41 ms | 677 | 673 MB | 752 ms | +| **Menü nachher 1920×1080** | **3,30 / 4,03 ms** | **3,24 ms** | **0,30 ms** | **397** | **1.055 MB** | **1.225 ms** | +| Bauphase nachher 1920×1080 | 3,46 / 4,29 ms | 3,38 ms | 0,49 ms | 931 | 1.299 MB | – | + +- Während das Menü sichtbar ist, rendert nur die Bühne. Die Arena dahinter wird ausgelassen (`disable_3d`). In der Partie ist die Bühne abgeschaltet: kein Bild-Update, keine Verarbeitung, gemessen nur noch ein Viewport. +- Das erste Bild erscheint etwa 0,48 s später. Die Formationen laden in Hintergrundthreads und sind in diesen Läufen zum ersten Bild bereit (Menüprüfung: 0,9 s nach Szenenstart). +- **Grafikspeicher +360 bis +380 MB im Menü:** Die Bühne lädt die Ringborke mit ihren 4K-Holztexturen, die vorher erst im Spiel geladen wurden. Die Bühne bleibt für eine schnelle Rückkehr ins Menü im Speicher. Auf Grafikkarten mit wenig Speicher ist das ungetestet. +- Paket-Ladezeiten und Messungen auf anderer Hardware liegen nicht vor. + +## Sichtprüfung + +[Vorher](screenshots/phase20/before) · [Nachher](screenshots/phase20/after) · [Gegenüberstellung](screenshots/phase20/comparison.png) · [Bewegung und Übergänge, 16,9 s](screenshots/phase20/menu-reel.mp4) ([GIF](screenshots/phase20/menu-reel.gif)). + +Geprüft in 1280×720 und 1920×1080: Titel, Bundauswahl beider Bünde, erweiterte Einstellungen, Tastaturfokus, Optionen, Ergebnisbildschirm, Spielansicht nach dem Start sowie das Paketmenü unter Vulkan und OpenGL. + +## Offen + +- Kein nativer Windows-Lauf, keine menschlichen Bedien- und Lesbarkeitstests. +- 21:9, 4K/HiDPI, andere GPU-Hersteller und Grafikkarten mit wenig Speicher sind ungetestet. +- Bei 16:9 liegt im Spiel jetzt heller Spielfeldbelag unter der halbtransparenten rechten Seitenleiste; das gehört zu Phase 20B (HUD). diff --git a/docs/phase20-builds.md b/docs/phase20-builds.md new file mode 100644 index 0000000..d9db82b --- /dev/null +++ b/docs/phase20-builds.md @@ -0,0 +1,36 @@ +# Demo 0.15.0 · Linux und Windows + +Stand: 27. September 2026. Neues Hauptmenü mit 3D-Bühne, Bundwahl über Karten, gemeinsames Menü-Theme; Funkenlanze und Glasballiste erstmals im Paket. + +| System | Paket | Größe | +| --- | --- | ---: | +| Linux | [Saumwacht-Linux-x64-0.15.0.zip](../../dist/Saumwacht-Linux-x64-0.15.0.zip) | 264,2 MiB | +| Windows | [Saumwacht-Windows-x64-0.15.0.zip](../../dist/Saumwacht-Windows-x64-0.15.0.zip) | 273,7 MiB | + +ZIP vollständig entpacken. Linux: `Spielen.sh`; Windows: `Saumwacht.exe`. Bei Vulkan-Problemen `Kompatibilitaet.sh` bzw. `Kompatibilitaet.bat`. + +## Nachweis + +Archive per CRC geprüft, außerhalb des Projekts entpackt, Programm-Hashes gleich dem Buildmanifest. LIESMICH nennt 0.15.0; die Lizenzen für Cantarell, Cinzel und Alegreya liegen bei. Das Linux-Paket wurde mit seinem offiziellen Release-Programm unter Vulkan (1920×1080) und OpenGL (1280×720) sowie in vier KI-Partien geprüft. Die Windows-Spieldaten wurden mit Godot unter Linux geprüft; **ein nativer Windows-Lauf steht aus**. [QA](phase20-QA.md) · [Paketintegrität](phase20-package-check.json). + +Paketänderungen gegenüber 0.14.0: + +- `assets/menu_stage_manifest.json` ist im Exportfilter eingetragen. +- Der Ausschluss `assets/ui/*` wurde auf die ungenutzten Altgrafiken `assets/ui/ui_*` eingeschränkt. Sonst hätten Embleme und Steuerungs-Icons im Paket gefehlt; der Paket-Smoke prüft sie jetzt. +- Versionen in Projekt, Presets und Builder: 0.15.0. + +## SHA-256 + +```text +994ff8b5ebf6758a5cb15d986aeb74be54831744a100fe1a8ef2d738c54b0328 Saumwacht-Linux-x64-0.15.0.zip +0d8bc5ed3f9f76180d02c85890c85c52b49802caa7c1adbc395c8e42fa324ddd Saumwacht-Windows-x64-0.15.0.zip +``` + +## Wiederholen + +```bash +python3 tools/build_demo.py --check-only +python3 tools/build_demo.py +./Saumwacht.x86_64 -- --smoke-test # im entpackten Linux-Paket +godot --headless --main-pack Saumwacht.exe -- --smoke-test # Windows-Spieldaten unter Linux +``` diff --git a/docs/phase20-logs/ability-events.log b/docs/phase20-logs/ability-events.log new file mode 100644 index 0000000..6659999 --- /dev/null +++ b/docs/phase20-logs/ability-events.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +ABILITY_EVENT_PASS: 33 checks; 0 failures +EXIT 0 diff --git a/docs/phase20-logs/expedition-test.log b/docs/phase20-logs/expedition-test.log new file mode 100644 index 0000000..116b634 --- /dev/null +++ b/docs/phase20-logs/expedition-test.log @@ -0,0 +1,9 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 206 checks; 0 failures; report /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json +WARNING: 6 ObjectDB instances were leaked at exit (run with `--verbose` for details). + at: cleanup (core/object/object.cpp:2536) +EXIT 0 diff --git a/docs/phase20-logs/faction-test.log b/docs/phase20-logs/faction-test.log new file mode 100644 index 0000000..38324ec --- /dev/null +++ b/docs/phase20-logs/faction-test.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json +EXIT 0 diff --git a/docs/phase20-logs/faction-ui-graphical.log b/docs/phase20-logs/faction-ui-graphical.log new file mode 100644 index 0000000..e8fb279 --- /dev/null +++ b/docs/phase20-logs/faction-ui-graphical.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.351 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 128 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json +EXIT 0 diff --git a/docs/phase20-logs/package-linux-faction.log b/docs/phase20-logs/package-linux-faction.log new file mode 100644 index 0000000..e3d5f38 --- /dev/null +++ b/docs/phase20-logs/package-linux-faction.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json +EXIT 0 diff --git a/docs/phase20-logs/package-linux-opengl-smoke.log b/docs/phase20-logs/package-linux-opengl-smoke.log new file mode 100644 index 0000000..a860c0e --- /dev/null +++ b/docs/phase20-logs/package-linux-opengl-smoke.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 615.71.09 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 473 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke +EXIT 0 diff --git a/docs/phase20-logs/package-linux-vulkan-smoke.log b/docs/phase20-logs/package-linux-vulkan-smoke.log new file mode 100644 index 0000000..0b34fa6 --- /dev/null +++ b/docs/phase20-logs/package-linux-vulkan-smoke.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.351 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 473 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke +EXIT 0 diff --git a/docs/phase20-logs/package-windows-faction.log b/docs/phase20-logs/package-windows-faction.log new file mode 100644 index 0000000..38324ec --- /dev/null +++ b/docs/phase20-logs/package-windows-faction.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json +EXIT 0 diff --git a/docs/phase20-logs/package-windows-smoke.log b/docs/phase20-logs/package-windows-smoke.log new file mode 100644 index 0000000..e7d111a --- /dev/null +++ b/docs/phase20-logs/package-windows-smoke.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 463 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke +EXIT 0 diff --git a/docs/phase20-logs/perf-after-1280x720.json b/docs/phase20-logs/perf-after-1280x720.json new file mode 100644 index 0000000..67bb393 --- /dev/null +++ b/docs/phase20-logs/perf-after-1280x720.json @@ -0,0 +1,25 @@ +{ + "canvas": "(1706.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 397.0, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 1242.88, + "frame_ms_mean": 1.81586501210654, + "frame_ms_p95": 2.415, + "frames": 3304, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 1.7511240920778, + "instantiate_ms": 758.174, + "label": "after", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "VORBEREITUNG", + "render_cpu_ms_mean": 0.273972457711141, + "renderer": "forward_plus", + "stage_ready_ms": 1242.901, + "static_mem_mb": 112.163498878479, + "video_mem_mb": 916.98942565918, + "viewports_measured": 2, + "vsync": "disabled", + "window": "(1280, 720)" +} \ No newline at end of file diff --git a/docs/phase20-logs/perf-after-1920x1080.json b/docs/phase20-logs/perf-after-1920x1080.json new file mode 100644 index 0000000..13b4bf9 --- /dev/null +++ b/docs/phase20-logs/perf-after-1920x1080.json @@ -0,0 +1,25 @@ +{ + "canvas": "(1706.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 397.0, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 1225.473, + "frame_ms_mean": 3.30424614537445, + "frame_ms_p95": 4.029, + "frames": 1816, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 3.23754900902723, + "instantiate_ms": 783.281, + "label": "after", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "VORBEREITUNG", + "render_cpu_ms_mean": 0.299429515692598, + "renderer": "forward_plus", + "stage_ready_ms": 1225.492, + "static_mem_mb": 116.989024162292, + "video_mem_mb": 1055.37028503418, + "viewports_measured": 2, + "vsync": "disabled", + "window": "(1920, 1080)" +} \ No newline at end of file diff --git a/docs/phase20-logs/perf-after-build-1280x720.json b/docs/phase20-logs/perf-after-build-1280x720.json new file mode 100644 index 0000000..5d15385 --- /dev/null +++ b/docs/phase20-logs/perf-after-build-1280x720.json @@ -0,0 +1,25 @@ +{ + "canvas": "(1706.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 930.730063514467, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 1208.057, + "frame_ms_mean": 2.11731157374735, + "frame_ms_p95": 2.861, + "frames": 2834, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 2.05155292836898, + "instantiate_ms": 784.087, + "label": "after-build", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "BAUPHASE", + "render_cpu_ms_mean": 0.466717007583771, + "renderer": "forward_plus", + "stage_ready_ms": 1208.083, + "static_mem_mb": 117.211266517639, + "video_mem_mb": 1054.48445129395, + "viewports_measured": 1, + "vsync": "disabled", + "window": "(1280, 720)" +} \ No newline at end of file diff --git a/docs/phase20-logs/perf-after-build-1920x1080.json b/docs/phase20-logs/perf-after-build-1920x1080.json new file mode 100644 index 0000000..c47bd20 --- /dev/null +++ b/docs/phase20-logs/perf-after-build-1920x1080.json @@ -0,0 +1,25 @@ +{ + "canvas": "(1706.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 930.739055299539, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 1219.527, + "frame_ms_mean": 3.45696947004608, + "frame_ms_p95": 4.289, + "frames": 1736, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 3.3768053016355, + "instantiate_ms": 781.246, + "label": "after-build", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "BAUPHASE", + "render_cpu_ms_mean": 0.49276612934223, + "renderer": "forward_plus", + "stage_ready_ms": 1219.548, + "static_mem_mb": 121.678281784058, + "video_mem_mb": 1298.80867004395, + "viewports_measured": 1, + "vsync": "disabled", + "window": "(1920, 1080)" +} \ No newline at end of file diff --git a/docs/phase20-logs/perf-before-1280x720.json b/docs/phase20-logs/perf-before-1280x720.json new file mode 100644 index 0000000..c10ee1f --- /dev/null +++ b/docs/phase20-logs/perf-before-1280x720.json @@ -0,0 +1,24 @@ +{ + "canvas": "(1600.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 677.0, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 746.43, + "frame_ms_mean": 2.15375628140704, + "frame_ms_p95": 2.871, + "frames": 2786, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 2.09686468012112, + "instantiate_ms": 571.902, + "label": "before", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "VORBEREITUNG", + "process_ms_mean": 6.37380689160073, + "render_cpu_ms_mean": 0.364563531954342, + "renderer": "forward_plus", + "static_mem_mb": 97.1528072357178, + "video_mem_mb": 554.012268066406, + "vsync": "disabled", + "window": "(1280, 720)" +} \ No newline at end of file diff --git a/docs/phase20-logs/perf-before-1920x1080.json b/docs/phase20-logs/perf-before-1920x1080.json new file mode 100644 index 0000000..4459416 --- /dev/null +++ b/docs/phase20-logs/perf-before-1920x1080.json @@ -0,0 +1,24 @@ +{ + "canvas": "(1600.0, 960.0)", + "cpu": "AMD Ryzen 5 5600X 6-Core Processor", + "draw_calls_mean": 677.0, + "driver": "1.4.351", + "engine": "4.7.2-stable (fedora)", + "first_frame_ms": 751.81, + "frame_ms_mean": 3.41939601139601, + "frame_ms_p95": 4.197, + "frames": 1755, + "gpu": "NVIDIA GeForce RTX 5060 Ti", + "gpu_ms_mean": 3.33334530126675, + "instantiate_ms": 570.913, + "label": "before", + "os": "Linux 44 (KDE Plasma Desktop Edition)", + "phase": "VORBEREITUNG", + "process_ms_mean": 10.7096455840457, + "render_cpu_ms_mean": 0.411781766068222, + "renderer": "forward_plus", + "static_mem_mb": 97.1364002227783, + "video_mem_mb": 672.953674316406, + "vsync": "disabled", + "window": "(1920, 1080)" +} \ No newline at end of file diff --git a/docs/phase20-logs/smoke-test.log b/docs/phase20-logs/smoke-test.log new file mode 100644 index 0000000..e7d111a --- /dev/null +++ b/docs/phase20-logs/smoke-test.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 463 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke +EXIT 0 diff --git a/docs/phase20-logs/test-runner.log b/docs/phase20-logs/test-runner.log new file mode 100644 index 0000000..ac5e7b6 --- /dev/null +++ b/docs/phase20-logs/test-runner.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. +EXIT 0 diff --git a/docs/phase20-logs/verify-glass.log b/docs/phase20-logs/verify-glass.log new file mode 100644 index 0000000..f8104a3 --- /dev/null +++ b/docs/phase20-logs/verify-glass.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RIG_PASS: 44 checks; 0 failures +EXIT 0 diff --git a/docs/phase20-logs/verify-menu-1280x720.log b/docs/phase20-logs/verify-menu-1280x720.log new file mode 100644 index 0000000..f980cad --- /dev/null +++ b/docs/phase20-logs/verify-menu-1280x720.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.351 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +MENU_VERIFY_PASS: 68 checks; 0 failures +EXIT 0 diff --git a/docs/phase20-logs/verify-menu-1920x1080.log b/docs/phase20-logs/verify-menu-1920x1080.log new file mode 100644 index 0000000..f980cad --- /dev/null +++ b/docs/phase20-logs/verify-menu-1920x1080.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.351 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +MENU_VERIFY_PASS: 68 checks; 0 failures +EXIT 0 diff --git a/docs/phase20-menu-verification.json b/docs/phase20-menu-verification.json new file mode 100644 index 0000000..1f619b8 --- /dev/null +++ b/docs/phase20-menu-verification.json @@ -0,0 +1,8 @@ +{ + "checks": 68, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "formations_ready_ms": 895, + "menu_instantiate_ms": 515, + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase20-package-check.json b/docs/phase20-package-check.json new file mode 100644 index 0000000..9e8e05a --- /dev/null +++ b/docs/phase20-package-check.json @@ -0,0 +1,41 @@ +{ + "version": "0.15.0", + "engine": "4.7.2.stable", + "packages": [ + { + "platform": "Linux", + "archive": "Saumwacht-Linux-x64-0.15.0.zip", + "sha256": "994ff8b5ebf6758a5cb15d986aeb74be54831744a100fe1a8ef2d738c54b0328", + "executable_sha256": "4063074ae495eb152d9db3cd9486d8797fb11b994e17611c06c129f4a7a3f95e", + "crc": "passed", + "exe_hash_matches_manifest": true, + "version_in_readme": "0.15.0", + "font_licenses": [ + "OFL-Alegreya.txt", + "OFL-Cantarell.txt", + "OFL-Cinzel.txt" + ] + }, + { + "platform": "Windows", + "archive": "Saumwacht-Windows-x64-0.15.0.zip", + "sha256": "0d8bc5ed3f9f76180d02c85890c85c52b49802caa7c1adbc395c8e42fa324ddd", + "executable_sha256": "428d7ff8d2ef5cbbae8777ef35923df4040e6bda0ec1775386e8675c4b3b19bb", + "crc": "passed", + "exe_hash_matches_manifest": true, + "version_in_readme": "0.15.0", + "font_licenses": [ + "OFL-Alegreya.txt", + "OFL-Cantarell.txt", + "OFL-Cinzel.txt" + ] + } + ], + "runs": { + "package-linux-vulkan-smoke": "EXPORT_SMOKE_PASS: 473 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035]", + "package-linux-opengl-smoke": "EXPORT_SMOKE_PASS: 473 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035]", + "package-linux-faction": "FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json", + "package-windows-smoke": "EXPORT_SMOKE_PASS: 463 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035]", + "package-windows-faction": "FACTION_PASS: 1665 checks; 0 failures; /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase10-verification.json" + } +} diff --git a/docs/phase5-balance.md b/docs/phase5-balance.md new file mode 100644 index 0000000..f88b4e9 --- /dev/null +++ b/docs/phase5-balance.md @@ -0,0 +1,92 @@ +# Glutpakt · Daten und vollständige Testpartien + +Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler. + +## Einheiten + +Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit. + +| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit | +| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- | +| g01 | Kohlenbeißer | 45 | 260 | 17 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s. | +| g02 | Schlackenklaue | 90 | 690 | 44 | 1.2 | Klinge | Schwer | Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s. | +| g03 | Schlackenwacht | 70 | 650 | 11 | 1.2 | Klinge | Schwer | Erste 8 s: 15 % weniger erlittener Schaden. | +| g04 | Basaltbastion | 150 | 1650 | 27 | 1.4 | Klinge | Schwer | Erste 10 s: 25 % weniger Schaden, danach 10 %. | +| g05 | Funkenlanze | 65 | 240 | 24 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: 50 % zusätzlicher Grundschaden. | +| g06 | Glasballiste | 140 | 640 | 65 | 6.5 | Durchschlag | Leicht | Jeder 4. Treffer: 75 % zusätzlicher Grundschaden. | +| g07 | Aschenwerfer | 95 | 310 | 23 | 4.5 | Impuls | Leicht | Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m. | +| g08 | Kraterrufer | 190 | 820 | 58 | 5.0 | Impuls | Schwer | Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m. | +| g09 | Herdhüter | 85 | 420 | 12 | 3.5 | Impuls | Ätherisch | Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden. | +| g10 | Sonnenesse | 170 | 1080 | 30 | 4.0 | Impuls | Ätherisch | Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung. | + +## Wellen + +| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor | +| ---: | --- | --- | ---: | ---: | +| 1 | Erste Risse | 8 × Splitterling | 1.000 | 1.000 | +| 2 | Splitterstrom | 10 × Splitterling | 1.150 | 1.084 | +| 3 | Harte Schalen | 6 × Splitterling, 4 × Schalenläufer | 1.320 | 1.176 | +| 4 | Fäden im Rücken | 8 × Splitterling, 4 × Fadenschütze | 1.510 | 1.276 | +| 5 | Der Bruchhirsch | 1 × Bruchhirsch, 6 × Splitterling | 1.720 | 1.384 | +| 6 | Gepanzerter Vorstoß | 6 × Schalenläufer, 6 × Splitterling | 1.950 | 1.500 | +| 7 | Stimmen aus dem Nebel | 8 × Nebelrest, 4 × Splitterling | 2.200 | 1.624 | +| 8 | Der letzte Riegel | 1 × Riegelkoloss, 2 × Schalenläufer, 3 × Fadenschütze | 2.470 | 1.756 | + +## Standard gegen Lernmodus + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 22.3 | 3000 / 3000 | 0 / 0 | 112 / 177 | 4 / 3 | +| 3 | 31.4 | 3000 / 2729 | 0 / 5 | 156 / 194 | 4 / 3 | +| 4 | 22.2 | 3000 / 2376 | 0 / 11 | 137 / 179 | 5 / 3 | +| 5 | 37.6 | 3000 / 2109 | 0 / 2 | 166 / 202 | 7 / 4 | +| 6 | 35.6 | 3000 / 1750 | 0 / 9 | 192 / 129 | 7 / 7 | +| 7 | 41.0 | 3000 / 1544 | 0 / 5 | 193 / 191 | 8 / 7 | +| 8 | 49.0 | 3000 / 1072 | 0 / 5 | 211 / 174 | 9 / 7 | + +Ergebnis: Front 0 gewinnt. + +## Standard gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 112 / 112 | 4 / 4 | +| 3 | 27.4 | 3000 / 3000 | 0 / 0 | 157 / 157 | 4 / 4 | +| 4 | 23.5 | 3000 / 3000 | 0 / 0 | 142 / 142 | 5 / 5 | +| 5 | 17.4 | 3000 / 3000 | 0 / 0 | 156 / 156 | 5 / 5 | +| 6 | 22.1 | 3000 / 3000 | 0 / 0 | 190 / 190 | 5 / 5 | +| 7 | 21.7 | 3000 / 3000 | 0 / 0 | 182 / 182 | 6 / 6 | +| 8 | 25.0 | 3000 / 3000 | 0 / 0 | 244 / 244 | 6 / 6 | + +Ergebnis: Gleichstand. + +## Leeres Baufeld gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 295 / 139 | 0 / 3 | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 373 / 112 | 0 / 4 | +| 3 | 19.9 | 2041 / 3000 | 11 / 0 | 454 / 150 | 0 / 4 | +| 4 | 21.4 | 1584 / 3000 | 13 / 0 | 538 / 151 | 0 / 5 | +| 5 | 15.3 | 1033 / 3000 | 8 / 0 | 625 / 161 | 0 / 5 | +| 6 | 17.4 | 304 / 3000 | 13 / 0 | 715 / 187 | 0 / 5 | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 715 / 37 | 0 / 5 | + +Ergebnis: Front 1 gewinnt. + +## Nachvollziehbarer Kaufplan gegen den Lernmodus + +Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern. + +| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs | +| ---: | --- | ---: | --- | +| 1 | Schlackenwacht, Funkenlanze, Kohlenbeißer | 0 | | +| 2 | Funkenlanze | 1 | | +| 3 | Schlackenklaue ↑ | 0 | s02 | +| 4 | Funkenlanze | 1 | s01 | +| 5 | Herdhüter, Kohlenbeißer | 0 | s01 | +| 6 | Glasballiste ↑ | 0 | s02 | +| 7 | Glasballiste ↑, Kohlenbeißer | 0 | s01 | +| 8 | Glasballiste ↑, Kohlenbeißer | 0 | s02 | diff --git a/docs/phase5-verification.json b/docs/phase5-verification.json new file mode 100644 index 0000000..78591c0 --- /dev/null +++ b/docs/phase5-verification.json @@ -0,0 +1,714 @@ +{ + "capture": true, + "checks": 351, + "failures": [], + "matches": [ + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 177 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 3 + ], + "seconds": 22.3333333333333, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2729 + ], + "damage": [ + 0, + 271 + ], + "gold": [ + 156, + 194 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 3 + ], + "seconds": 31.4333333333328, + "sends": [ + "s02" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 2376 + ], + "damage": [ + 0, + 353 + ], + "gold": [ + 137, + 179 + ], + "leaks": [ + 0, + 11 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 3 + ], + "seconds": 22.15, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2109 + ], + "damage": [ + 0, + 267 + ], + "gold": [ + 166, + 202 + ], + "leaks": [ + 0, + 2 + ], + "purchases": [ + "Herdhüter", + "Kohlenbeißer" + ], + "roster": [ + 7, + 4 + ], + "seconds": 37.6333333333325, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1750 + ], + "damage": [ + 0, + 359 + ], + "gold": [ + 192, + 129 + ], + "leaks": [ + 0, + 9 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 7, + 7 + ], + "seconds": 35.5999999999993, + "sends": [ + "s02" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1544 + ], + "damage": [ + 0, + 206 + ], + "gold": [ + 193, + 191 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 8, + 7 + ], + "seconds": 40.9666666666656, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1072 + ], + "damage": [ + 0, + 472 + ], + "gold": [ + 211, + 174 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 9, + 7 + ], + "seconds": 49.0166666666652, + "sends": [ + "s02" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 112 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 157, + 157 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 4 + ], + "seconds": 27.3666666666664, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 142, + 142 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 5 + ], + "seconds": 23.5166666666666, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 156, + 156 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 17.366666666667, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 190, + 190 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 182, + 182 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 6, + 6 + ], + "seconds": 21.6833333333334, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 244, + 244 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Basaltbastion ↑" + ], + "roster": [ + 6, + 6 + ], + "seconds": 24.9666666666665, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "damage": [ + 200, + 0 + ], + "gold": [ + 295, + 139 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 3 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "damage": [ + 270, + 0 + ], + "gold": [ + 373, + 112 + ], + "leaks": [ + 10, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "damage": [ + 489, + 0 + ], + "gold": [ + 454, + 150 + ], + "leaks": [ + 11, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 19.8833333333335, + "sends": [], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "damage": [ + 457, + 0 + ], + "gold": [ + 538, + 151 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 21.4000000000001, + "sends": [], + "wave": 4, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "damage": [ + 551, + 0 + ], + "gold": [ + 625, + 161 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 15.3333333333337, + "sends": [], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 304, + 3000 + ], + "damage": [ + 729, + 0 + ], + "gold": [ + 715, + 187 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 17.4000000000003, + "sends": [], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 0, + 3000 + ], + "damage": [ + 304, + 0 + ], + "gold": [ + 715, + 37 + ], + "leaks": [ + 12, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers_ordered": 0 + } + ] + } + ], + "wave_count": 8 +} \ No newline at end of file diff --git a/docs/phase6-QA.md b/docs/phase6-QA.md new file mode 100644 index 0000000..443d273 --- /dev/null +++ b/docs/phase6-QA.md @@ -0,0 +1,59 @@ +# Phase 6 · Prüfprotokoll der Demo 0.6.0 + +Stand: **15. September 2026**. Entwicklung mit Godot `4.7.2.stable.fedora.ed1daf0bf`, Exporte mit den offiziellen Release-Templates `4.7.2.stable.official.ed1daf0bf`. Grafikprüfung unter Linux mit NVIDIA GeForce RTX 5060 Ti, OpenGL Compatibility. + +## Ergebnis + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | **209 Prüfungen bestanden** | +| Drei reguläre vollständige Partien | **343 Prüfungen bestanden**, Sieg / Gleichstand / Niederlage | +| Aus ZIP entpackte Linux-Demo ohne Projektordner, headless | **141 Prüfungen bestanden**, offizielle Release-Engine | +| Dieselbe entpackte Linux-Demo mit Anzeige | **147 Prüfungen bestanden**, sechs tatsächliche Viewport-Aufnahmen | +| Eingebettetes PCK der Windows-EXE mit Linux-Godot | **141 Prüfungen bestanden**, einschließlich Acht-Wellen-Partie | +| Kamera, Fokus, Optionspause, Ton und Begrenzung bei 2× | **9 Prüfungen bestanden** | +| Bedienung | Menüstart, bezahlte Startformation, Space trotz Buttonfokus, Pause, Tab, Folgewelle, echte Mausplatzierung und Rückgängig bestanden | +| 49 GLB-Dateien | **49/49 bestanden**, keine Topologiewarnungen, 20/20 Upgrade-Paare unterscheidbar | +| Eigenständige Blender-Skripte | **9/9 bestanden**, isolierte native Szene erneut geöffnet | +| ZIP-Pakete | CRC, Inhalt und SHA-256 geprüft; enthaltene EXE/ELF stimmen mit dem Buildmanifest überein | +| Windows-Ausführung | **Nicht durchgeführt**; kein Windows-System oder Wine vorhanden | + +Die Regression verwendet reale Startressourcen und simuliert Kämpfe in festen 1/60-s-Schritten. Ergebnisse: Standard gegen Lernmodus gewinnt in Welle 8 mit **3.000 / 1.035 Kern-HP**, Standard gegen Standard endet mit **3.000 / 3.000**, leeres Baufeld verliert in Welle 7 mit **0 / 3.000**. Die größere Trennung verbündeter Figuren verändert den bisherigen Kaufplan nicht. Siehe [Balance und Kaufplan](phase6-balance.md), [Abnahmedaten](phase6-verification.json). + +Zwei Regeltest-Fixtures erhöhen ausschließlich ihren lokalen Gold-/HP-Zustand für Grenzwerte und Phasenübergänge. Die drei Abnahmepartien und die Release-Paketpartie verwenden normale Ressourcen. KI-geführte Testpartien sind keine Erfolgsquote für menschliche Spieler. + +## Neue Technik und Messung + +Für jeden der zehn Glutpakt-Wächter prüft der Pakettest vollständige Dreieckszahlen und identische Bounds der neutralen Gelenkpose, getrennte Beinbewegungen, gemeinsame unveränderliche Meshes und unabhängige Instanztransforms/Trefferfarben. Das statische Batching der 49 Assets ergibt jetzt **260 Materialflächen aus 1.848 Quellteilen**; bewegliche Wächter benötigen mehrere Gelenkgruppen. Alle 13 Audioclips und erforderlichen Icons werden aus dem Paket geladen. + +Ein **12 Sekunden langer, tatsächlich gerenderter Bosskampf in Welle 8 bei 2×**, nach zwei Sekunden Aufwärmzeit, umfasst zu Messbeginn 28 Kampfinstanzen. Auf dieser Maschine wurden **143,4 FPS im Mittel**, **6,97 ms mittlere Framezeit**, **8,35 ms 95. Perzentil** und maximal **2.172 Draw Calls** gemessen. VSync und andere Rechnerbedingungen sind nicht kontrolliert; dies ist ein lokaler Stichprobentest, keine Mindesthardware- oder allgemeine FPS-Zusage. In der Messzeit starteten 54 Klangeffekte. [Messdaten](phase6-runtime.json). + +Eine separate Prüfung bestätigt, dass ein unmittelbar identischer Effekt innerhalb der Cooldown-Zeit abgewiesen wird. Bei Spielende werden Audiowiedergaben vor dem Schließen freigegeben. + +## Aufnahmen des exportierten Spiels + +- [Menü](screenshots/phase6/menu.png) +- [Optionen und Hilfe](screenshots/phase6/options.png) +- [Bauphase](screenshots/phase6/build.png) +- [Kampf](screenshots/phase6/combat.png) +- [Finaler Boss](screenshots/phase6/boss.png) +- [Sieg](screenshots/phase6/victory.png) + +Die Aufnahmen stammen aus der aus dem finalen ZIP entpackten Linux-Demo, ohne Editor oder Quellprojekt. Keine nachträgliche Bildbearbeitung. Zusätzlich wurden die fünf [Glutpakt-Referenzvergleiche](screenshots/phase4/reference-gallery.html) mit den aktualisierten Materialien erneut gerendert. + +## Wiederholen + +Aus dem Godot-Projektordner: + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . res://tools/verify_phase5.tscn -- --phase6 +godot --path . res://tools/screenshot.tscn +godot --path . res://tools/verify_phase6_runtime.tscn +``` + +Die ersten beiden Befehle prüfen Regeln und vollständige Partien. Der dritte prüft die Eingaben; der vierte benötigt Grafik und Ton. Paketprüfung und Buildbefehle stehen unter [Builds](phase6-builds.md). Wesentliche Laufprotokolle liegen in `docs/phase6-logs`. + +## Grenzen + +Kein menschlicher Langzeittest und kein nativer Windows-Lauf. Die Prüfung des Windows-PCK unter Linux belegt die enthaltenen Spieldaten; Windows-Grafik-, Audio-, Eingabe- und Startverhalten müssen auf Windows geprüft werden. Die EXE ist nicht signiert. Modelle und Bewegungen sind vereinfacht; die Glutpakt-Illustrationen werden nicht detailgetreu rekonstruiert. Es gibt keine Musik, Spielstandspeicherung oder Netzwerkfunktionen. Optionen werden lokal gespeichert. diff --git a/docs/phase6-balance.md b/docs/phase6-balance.md new file mode 100644 index 0000000..0012117 --- /dev/null +++ b/docs/phase6-balance.md @@ -0,0 +1,92 @@ +# Glutpakt · Daten und vollständige Testpartien + +Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler. + +## Einheiten + +Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit. + +| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit | +| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- | +| g01 | Kohlenbeißer | 45 | 260 | 17 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s. | +| g02 | Schlackenklaue | 90 | 690 | 44 | 1.2 | Klinge | Schwer | Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s. | +| g03 | Schlackenwacht | 70 | 650 | 11 | 1.2 | Klinge | Schwer | Erste 8 s: 15 % weniger erlittener Schaden. | +| g04 | Basaltbastion | 150 | 1650 | 27 | 1.4 | Klinge | Schwer | Erste 10 s: 25 % weniger Schaden, danach 10 %. | +| g05 | Funkenlanze | 65 | 240 | 24 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: 50 % zusätzlicher Grundschaden. | +| g06 | Glasballiste | 140 | 640 | 65 | 6.5 | Durchschlag | Leicht | Jeder 4. Treffer: 75 % zusätzlicher Grundschaden. | +| g07 | Aschenwerfer | 95 | 310 | 23 | 4.5 | Impuls | Leicht | Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m. | +| g08 | Kraterrufer | 190 | 820 | 58 | 5.0 | Impuls | Schwer | Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m. | +| g09 | Herdhüter | 85 | 420 | 12 | 3.5 | Impuls | Ätherisch | Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden. | +| g10 | Sonnenesse | 170 | 1080 | 30 | 4.0 | Impuls | Ätherisch | Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung. | + +## Wellen + +| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor | +| ---: | --- | --- | ---: | ---: | +| 1 | Erste Risse | 8 × Splitterling | 1.000 | 1.000 | +| 2 | Splitterstrom | 10 × Splitterling | 1.150 | 1.084 | +| 3 | Harte Schalen | 6 × Splitterling, 4 × Schalenläufer | 1.320 | 1.176 | +| 4 | Fäden im Rücken | 8 × Splitterling, 4 × Fadenschütze | 1.510 | 1.276 | +| 5 | Der Bruchhirsch | 1 × Bruchhirsch, 6 × Splitterling | 1.720 | 1.384 | +| 6 | Gepanzerter Vorstoß | 6 × Schalenläufer, 6 × Splitterling | 1.950 | 1.500 | +| 7 | Stimmen aus dem Nebel | 8 × Nebelrest, 4 × Splitterling | 2.200 | 1.624 | +| 8 | Der letzte Riegel | 1 × Riegelkoloss, 2 × Schalenläufer, 3 × Fadenschütze | 2.470 | 1.756 | + +## Standard gegen Lernmodus + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 22.3 | 3000 / 3000 | 0 / 0 | 112 / 177 | 4 / 3 | +| 3 | 32.1 | 3000 / 2733 | 0 / 5 | 156 / 191 | 4 / 3 | +| 4 | 22.1 | 3000 / 2380 | 0 / 11 | 137 / 176 | 5 / 3 | +| 5 | 36.4 | 3000 / 2091 | 0 / 2 | 166 / 199 | 7 / 4 | +| 6 | 36.9 | 3000 / 1716 | 0 / 9 | 192 / 171 | 7 / 6 | +| 7 | 46.6 | 3000 / 1584 | 0 / 4 | 193 / 179 | 8 / 6 | +| 8 | 50.0 | 3000 / 1035 | 0 / 5 | 211 / 162 | 9 / 6 | + +Ergebnis: Front 0 gewinnt. + +## Standard gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 112 / 112 | 4 / 4 | +| 3 | 27.3 | 3000 / 3000 | 0 / 0 | 157 / 157 | 4 / 4 | +| 4 | 23.2 | 3000 / 3000 | 0 / 0 | 142 / 142 | 5 / 5 | +| 5 | 17.7 | 3000 / 3000 | 0 / 0 | 156 / 156 | 5 / 5 | +| 6 | 22.1 | 3000 / 3000 | 0 / 0 | 190 / 190 | 5 / 5 | +| 7 | 20.8 | 3000 / 3000 | 0 / 0 | 182 / 182 | 6 / 6 | +| 8 | 25.0 | 3000 / 3000 | 0 / 0 | 244 / 244 | 6 / 6 | + +Ergebnis: Gleichstand. + +## Leeres Baufeld gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 295 / 139 | 0 / 3 | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 373 / 112 | 0 / 4 | +| 3 | 20.0 | 2041 / 3000 | 11 / 0 | 454 / 150 | 0 / 4 | +| 4 | 20.1 | 1584 / 3000 | 13 / 0 | 538 / 151 | 0 / 5 | +| 5 | 15.3 | 1033 / 3000 | 8 / 0 | 625 / 161 | 0 / 5 | +| 6 | 18.1 | 304 / 3000 | 13 / 0 | 715 / 187 | 0 / 5 | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 715 / 37 | 0 / 5 | + +Ergebnis: Front 1 gewinnt. + +## Nachvollziehbarer Kaufplan gegen den Lernmodus + +Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern. + +| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs | +| ---: | --- | ---: | --- | +| 1 | Schlackenwacht, Funkenlanze, Kohlenbeißer | 0 | | +| 2 | Funkenlanze | 1 | | +| 3 | Schlackenklaue ↑ | 0 | s02 | +| 4 | Funkenlanze | 1 | s01 | +| 5 | Herdhüter, Kohlenbeißer | 0 | s01 | +| 6 | Glasballiste ↑ | 0 | s02 | +| 7 | Glasballiste ↑, Kohlenbeißer | 0 | s01 | +| 8 | Glasballiste ↑, Kohlenbeißer | 0 | s02 | diff --git a/docs/phase6-builds.md b/docs/phase6-builds.md new file mode 100644 index 0000000..3f742bb --- /dev/null +++ b/docs/phase6-builds.md @@ -0,0 +1,42 @@ +# Demo 0.6.0 · Windows und Linux + +## Starten + +Im übergeordneten `dist`-Ordner liegen zwei ZIP-Pakete. Vollständig entpacken. Unter Windows `Saumwacht.exe`, unter Linux `Spielen.sh` oder `Saumwacht.x86_64` starten. Die Programme enthalten ihr PCK; der Projektordner wird nicht benötigt. + +Die Windows-Demo ist ein nicht signiertes x86-64-GUI-Programm. Sie wird für Windows 10/11 mit OpenGL-3.3-fähiger Grafik bereitgestellt. Ein echter Windows-Test steht aus. Die Linux-Demo wurde mit NVIDIA RTX 5060 Ti unter Fedora geprüft; daraus folgt keine Leistungszusage für andere Hardware. + +## Erstellen + +Verwendet werden die offiziellen Release-Templates von [Godot 4.7.2](https://godotengine.org/download/archive/4.7.2-stable/). Die installierte Fedora-Engine und die offiziellen Templates melden denselben Commit `ed1daf0bf`. Godots [Exportdokumentation](https://docs.godotengine.org/en/4.7/tutorials/export/exporting_projects.html) beschreibt das zugrunde liegende Verfahren. + +Die zwei benötigten Dateien aus dem offiziellen TPZ-Archiv liegen unter `assets-source/phase6/export-templates`: + +- `linux_release.x86_64` +- `windows_release_x86_64.exe` +- `version.txt`: `4.7.2.stable` + +Der Quellordner wird durch `.gdignore` nicht in das Spiel aufgenommen. Falls die Templates fehlen, das Standard-Archiv von der oben verlinkten offiziellen Downloadseite beziehen, als ZIP öffnen und nur diese Dateien in den genannten Ordner kopieren. + +```bash +python3 tools/build_demo.py +``` + +`export_presets.cfg` definiert Linux und Windows. Beide nutzen eingebettetes PCK und x86-64. Dokumentation, Entwicklungswerkzeuge, Tests und nicht verwendete UI-/Kartenillustrationen sind ausgeschlossen. Die dynamisch geladenen Assetmanifeste sind ausdrücklich enthalten. Die noch nicht spielbaren Fraktionsmodelle bleiben im Assetkatalog enthalten; die Spielauswahl ist weiterhin Glutpakt. + +Der Build-Schritt schreibt EXE/ELF, ZIPs, Anleitungen, `build-manifest.json`, `SHA256SUMS.txt` und Exportprotokolle in `../dist`. Er benötigt die vorhandenen Lizenzquellen unter `assets-source/phase6/licenses`. + +## Paketprüfung + +```bash +# Außerhalb des Projektordners ausführen: +/path/to/dist/linux/Saumwacht.x86_64 --headless -- --smoke-test +/path/to/dist/linux/Saumwacht.x86_64 -- --smoke-test + +# Prüft Windows-Spieldaten mit der Linux-Engine, nicht den Windows-Prozess: +godot --headless --main-pack /path/to/dist/windows/Saumwacht.exe -- --smoke-test +``` + +Der explizite Prüfmodus testet Gelenkgeometrie, unabhängige Instanzen, gebündelte Audio-/Bildassets, Optionspause, Fokus, Kamera, Einstellungsdateien und eine komplette bezahlte Acht-Wellen-Partie. Graphisch speichert er sechs unveränderte Viewport-Aufnahmen unter `user://phase6-smoke`. Ohne `--smoke-test` läuft das normale Spiel. + +Einstellungen liegen in `user://preferences.cfg`: unter Windows normalerweise `%APPDATA%/Godot/app_userdata/Saumwacht · Glutpakt`, unter Linux `~/.local/share/godot/app_userdata/Saumwacht · Glutpakt`. Der Test verwendet für seinen Einstellungs-Rundlauf eine eigene temporäre Datei und stellt die vorherigen Einstellungen wieder her. diff --git a/docs/phase6-logs/phase6-acceptance-final.log b/docs/phase6-logs/phase6-acceptance-final.log new file mode 100644 index 0000000..7c89649 --- /dev/null +++ b/docs/phase6-logs/phase6-acceptance-final.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RUNTIME_BATCHING: 1848 original parts -> 260 material surfaces across 49 assets +SLICE_MATCH: Standard gegen Lernmodus; wave 8; outcome 0; cores [3000, 1035] +SLICE_MATCH: Standard gegen Standard; wave 8; outcome -1; cores [3000, 3000] +SLICE_MATCH: Leeres Baufeld gegen Standard; wave 7; outcome 1; cores [0, 3000] +PHASE5_PASS: 343 checks; 3 real-budget matches; 0 failures diff --git a/docs/phase6-logs/phase6-glb-final.log b/docs/phase6-logs/phase6-glb-final.log new file mode 100644 index 0000000..8a7c033 --- /dev/null +++ b/docs/phase6-logs/phase6-glb-final.log @@ -0,0 +1,3 @@ +Phase 4 GLB audit: 49/49 assets passed +Upgrade pairs: 20/20 distinct +Warnings: 0 diff --git a/docs/phase6-logs/phase6-linux-zip-headless.log b/docs/phase6-logs/phase6-linux-zip-headless.log new file mode 100644 index 0000000..107d20b --- /dev/null +++ b/docs/phase6-logs/phase6-linux-zip-headless.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 141 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-package-data/godot/app_userdata/Saumwacht · Glutpakt/phase6-smoke diff --git a/docs/phase6-logs/phase6-linux-zip-visual.log b/docs/phase6-logs/phase6-linux-zip-visual.log new file mode 100644 index 0000000..f8a11f9 --- /dev/null +++ b/docs/phase6-logs/phase6-linux-zip-visual.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 147 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-package-data/godot/app_userdata/Saumwacht · Glutpakt/phase6-smoke diff --git a/docs/phase6-logs/phase6-rules-final.log b/docs/phase6-logs/phase6-rules-final.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase6-logs/phase6-rules-final.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase6-logs/phase6-runtime-final.log b/docs/phase6-logs/phase6-runtime-final.log new file mode 100644 index 0000000..ed0199e --- /dev/null +++ b/docs/phase6-logs/phase6-runtime-final.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +PHASE6_RUNTIME: {"audio_events":54,"checks":9,"device":"NVIDIA GeForce RTX 5060 Ti","engine":"4.7.2-stable (fedora)","failures":[],"frames":1721,"max_draw_calls":2172,"mean_fps":143.393448877403,"mean_frame_ms":6.97381929110982,"p95_frame_ms":8.349,"sample_seconds":12,"speed":2,"units_at_start":28,"viewport":"(1600.0, 960.0)","wave":8} diff --git a/docs/phase6-logs/phase6-standalone.log b/docs/phase6-logs/phase6-standalone.log new file mode 100644 index 0000000..183bd13 --- /dev/null +++ b/docs/phase6-logs/phase6-standalone.log @@ -0,0 +1,1022 @@ +00:00.016 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.016 color_management | Using fallback mode for management +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_melee.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +23:34:54 | INFO: Starting glTF 2.0 export +23:34:54 | INFO: Extracting primitive: ArmL0_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL0_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL0_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL0_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL1_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL1_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL1_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL1_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL2_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL2_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL2_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL2_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmL_Shoulder_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR0_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR0_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR0_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR0_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR1_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR1_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR1_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR1_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR2_Housing_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR2_Pivot_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR2_Pivot_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR2_Rod_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: ArmR_Shoulder_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Body_Breastplate_Face_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Body_Breastplate_Rim_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Body_HipPlateL_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Body_HipPlateR_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Body_Waist_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Head_Eye1_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Head_Eye_1_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Head_Face_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_AnkleGold_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Greave_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Knee_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Knee_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Piston_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Shin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_ThighArmor_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Toe0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg0_Toe1_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_AnkleGold_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Greave_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Knee_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Knee_Pin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Piston_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Shin_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_ThighArmor_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Toe0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: Leg1_Toe1_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponL0_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponL1_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponL2_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponR0_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponR1_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Extracting primitive: WeaponR2_Blade0_Mesh +23:34:54 | INFO: Primitives created: 1 +23:34:54 | INFO: Finished glTF 2.0 export in 0.06232929229736328 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_tank.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED m04: 1398 triangles, 60 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_m04.glb +STANDALONE_PASS: m04 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_GoldBelt_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Keep_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Bastion_Window0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_GoldBelt_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Keep_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Window0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Castle_Window1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Cuff_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmL_Elbow_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Hand_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Lower_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Upper_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_GoldBelt_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Keep_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Bastion_Window0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_GoldBelt_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Keep_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Window0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Castle_Window1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Cuff_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmR_Elbow_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Hand_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Lower_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Upper_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Body_ShieldEmber_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ShieldLineL_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Body_ShieldLineR_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Body_ShieldRidge_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Body_StoneMass_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Body_TowerShield_Face_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Body_TowerShield_Rim_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_GoldBelt_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Keep_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Merlon0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Merlon1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Merlon2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Merlon3_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CentralKeep_Window0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_VerticalEmber_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_AnkleBand_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegL_Joint_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegL_Knee_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Shin_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Thigh_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Toe0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Toe1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_AnkleBand_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegR_Joint_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegR_Knee_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Shin_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Thigh_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Toe0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Toe1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Finished glTF 2.0 export in 0.12475228309631348 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_ranged.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED g04: 1780 triangles, 71 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_g04.glb +STANDALONE_PASS: g04 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ClimbingVine_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_TwistedStem_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_Cup_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SeedLauncher_Seed_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.04183316230773926 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_artillery.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w06: 1178 triangles, 53 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_w06.glb +STANDALONE_PASS: w06 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: ArmL_Sickle_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Sickle_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ArchMask_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ArchMask_Eye1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ArchMask_Eye_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_BellSkirt_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CathedralFrontArch_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CathedralShell_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CentralFlow_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_TailL_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_TailR_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_WispL_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_WispR_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CentralSpire_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SpireL_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_SpireR_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_Clapper_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_ClapperChain_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.017747163772583008 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_support.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED n08: 1482 triangles, 18 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_n08.glb +STANDALONE_PASS: n08 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: Arm_BasinVine1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_BasinVine_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Heart_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_FrontVine1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_FrontVine_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_SpringArch1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_SpringArch_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf4_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf5_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_CanopyLeaf6_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Moss3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_Root3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe0_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe1_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe2_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Leg_RootToe3_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_LeafBasin_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_Water_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.04797720909118652 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_mercenary.py:224: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w10: 1290 triangles, 59 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_w10.glb +STANDALONE_PASS: w10 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: ArmL_Glove_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Lower_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_PauldronCap_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Upper_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Glove_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Lower_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_PauldronCap_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Upper_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Armor_Face_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Armor_Rim_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Belt_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Tabard_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Crest_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Eye1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Eye_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_HelmetBack_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Visor_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_VisorSlit_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_Boot_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_KneePlate_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_Shin_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_Strap_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_Thigh_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_Boot_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_KneePlate_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_Shin_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_Strap_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_Thigh_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_Haft_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_Head_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_TriangleInset_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_TriangleRim_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_Wedge_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.030119895935058594 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_worker.py:188: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED s04: 692 triangles, 35 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_s04.glb +STANDALONE_PASS: s04 +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: ArmL_Hand_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Hand_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Apron_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ApronPocket_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ApronStrap1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_ApronStrap_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Buckle1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Buckle_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_Clay_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_ClayFace_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Eye1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Eye_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_EyeSocket1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_EyeSocket_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_Hood_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_HoodEdge_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegL_Foot_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: LegR_Foot_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_CollectedSpark_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_CollectorProng1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_CollectorProng_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_CollectorStaff_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_LanternCap0_27_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_LanternCap0_53_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_LanternGlass_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Weapon_LanternHandle_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.026352405548095703 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_lane.py:187: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED worker: 968 triangles, 28 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/worker.glb +STANDALONE_PASS: worker +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: Body_LaneFoundation_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_00_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_01_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_02_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_03_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_04_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LaneSlab_05_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LBasalt_00_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LBasalt_01_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LBasalt_02_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LBrassMarker_00_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LBrassMarker_01_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LMoss_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_LRetainingLip_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RBasalt_00_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RBasalt_01_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RBasalt_02_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RBrassMarker_00_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RBrassMarker_01_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RMoss_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_RRetainingLip_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.02211141586303711 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_core.py:199: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED map_lane_segment: 316 triangles, 21 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/map_lane_segment.glb +STANDALONE_PASS: map_lane_segment +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: Arm_Cradle_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_Cradle_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_Cradle_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_Cradle_3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_CradleClasp_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_CradleClasp_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_CradleClasp_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Arm_CradleClasp_3_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_BrassPlinthRim_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CoreCrystal_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CorePlinth_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Body_CradleStep_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Team_Triangle_0_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Team_Triangle_1_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Team_Triangle_2_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Finished glTF 2.0 export in 0.0159914493560791 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_melee.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED core_team1: 332 triangles, 15 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/core_team1.glb +STANDALONE_PASS: core_team1 +STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved +23:34:55 | INFO: Starting glTF 2.0 export +23:34:55 | INFO: Extracting primitive: ArmL_Elbow_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_GoldPlate_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmL_Hand_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Lower_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmL_Upper_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Elbow_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_GoldPlate_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: ArmR_Hand_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Lower_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: ArmR_Upper_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Body_BackRock_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Body_MoltenCore_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_BrowL_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_BrowR_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CheekL_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CheekR_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CragCrown_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_CrownGold_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: Head_EyeL_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_EyeR_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_GlowingJaw_Mesh +23:34:55 | INFO: Primitives created: 1 +23:34:55 | INFO: Extracting primitive: Head_LowerFangL0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_LowerFangL1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_LowerFangL2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_LowerFangR0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_LowerFangR1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_LowerFangR2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangL0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangL1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangL2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangR0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangR1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: Head_UpperFangR2_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_AnkleBand_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegL_Joint_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegL_Knee_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Shin_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Thigh_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Toe0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegL_Toe1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_AnkleBand_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegR_Joint_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: LegR_Knee_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Shin_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Thigh_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Toe0_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: LegR_Toe1_Mesh +23:34:55 | INFO: Primitives created: 4 +23:34:55 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +23:34:55 | INFO: Primitives created: 3 +23:34:55 | INFO: Finished glTF 2.0 export in 0.10692572593688965 s +/tmp/saumwacht-standalone-zwr9e09b/scripts/create_melee.py:251: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED g01: 1064 triangles, 53 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_g01.glb +STANDALONE_PASS: g01 +23:34:56 | INFO: Starting glTF 2.0 export +23:34:56 | INFO: Extracting primitive: ArmL_Elbow_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmL_GoldPlate_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: ArmL_Hand_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmL_Lower_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmL_Shoulder_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmL_Upper_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmR_Elbow_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmR_GoldPlate_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: ArmR_Hand_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmR_Lower_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmR_Shoulder_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: ArmR_Upper_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Body_BackRock_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Body_MoltenCore_Mesh.001 +23:34:56 | INFO: Primitives created: 1 +23:34:56 | INFO: Extracting primitive: Head_BrowL_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_BrowR_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_CheekL_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_CheekR_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_CragCrown_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_CrownGold_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: Head_EyeL_Mesh.001 +23:34:56 | INFO: Primitives created: 1 +23:34:56 | INFO: Extracting primitive: Head_EyeR_Mesh.001 +23:34:56 | INFO: Primitives created: 1 +23:34:56 | INFO: Extracting primitive: Head_GlowingJaw_Mesh.001 +23:34:56 | INFO: Primitives created: 1 +23:34:56 | INFO: Extracting primitive: Head_LowerFangL0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_LowerFangL1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_LowerFangL2_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_LowerFangR0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_LowerFangR1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_LowerFangR2_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangL0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangL1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangL2_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangR0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangR1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: Head_UpperFangR2_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegL_AnkleBand_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: LegL_Joint_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: LegL_Knee_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegL_Shin_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegL_Thigh_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegL_Toe0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegL_Toe1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegR_AnkleBand_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: LegR_Joint_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: LegR_Knee_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegR_Shin_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegR_Thigh_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegR_Toe0_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: LegR_Toe1_Mesh.001 +23:34:56 | INFO: Primitives created: 4 +23:34:56 | INFO: Extracting primitive: WeaponL_Claw0_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: WeaponL_Claw1_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: WeaponR_Claw0_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Extracting primitive: WeaponR_Claw1_Mesh.001 +23:34:56 | INFO: Primitives created: 3 +23:34:56 | INFO: Finished glTF 2.0 export in 0.08412790298461914 s +00:02.321 blend | Read blend: "/tmp/saumwacht-standalone-zwr9e09b/blend/n08.blend" + +EXPORTED g01: 1064 triangles, 53 parts -> /tmp/saumwacht-standalone-zwr9e09b/exports/unit_g01.glb +STANDALONE_PASS: g01 +KEEP_SCENE_PASS: two generated scenes and original scene retained +Warning: Library file, loading empty scene +NATIVE_BLEND_PASS: isolated N08 scene reopened; 20 objects +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase6-logs/phase6-ui-final.log b/docs/phase6-logs/phase6-ui-final.log new file mode 100644 index 0000000..b33cb04 --- /dev/null +++ b/docs/phase6-logs/phase6-ui-final.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +Saved res://docs/screenshots/menu-overlay.png +Saved res://docs/screenshots/build-phase.png +Saved res://docs/screenshots/combat-phase.png +PASS: HUD start, formation, keyboard shortcuts with button focus, combat, pause, front switch, next wave, mouse placement and undo. diff --git a/docs/phase6-logs/phase6-windows-zip-pck.log b/docs/phase6-logs/phase6-windows-zip-pck.log new file mode 100644 index 0000000..626c8a7 --- /dev/null +++ b/docs/phase6-logs/phase6-windows-zip-pck.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 141 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-package-data/godot/app_userdata/Saumwacht · Glutpakt/phase6-smoke diff --git a/docs/phase6-runtime.json b/docs/phase6-runtime.json new file mode 100644 index 0000000..387f836 --- /dev/null +++ b/docs/phase6-runtime.json @@ -0,0 +1,17 @@ +{ + "audio_events": 54, + "checks": 9, + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "4.7.2-stable (fedora)", + "failures": [], + "frames": 1721, + "max_draw_calls": 2172, + "mean_fps": 143.393448877403, + "mean_frame_ms": 6.97381929110982, + "p95_frame_ms": 8.349, + "sample_seconds": 12, + "speed": 2, + "units_at_start": 28, + "viewport": "(1600.0, 960.0)", + "wave": 8 +} \ No newline at end of file diff --git a/docs/phase6-verification.json b/docs/phase6-verification.json new file mode 100644 index 0000000..d302ee7 --- /dev/null +++ b/docs/phase6-verification.json @@ -0,0 +1,714 @@ +{ + "capture": false, + "checks": 343, + "failures": [], + "matches": [ + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 177 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 3 + ], + "seconds": 22.3333333333333, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2733 + ], + "damage": [ + 0, + 267 + ], + "gold": [ + 156, + 191 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 3 + ], + "seconds": 32.1499999999995, + "sends": [ + "s02" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 2380 + ], + "damage": [ + 0, + 353 + ], + "gold": [ + 137, + 176 + ], + "leaks": [ + 0, + 11 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 3 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2091 + ], + "damage": [ + 0, + 289 + ], + "gold": [ + 166, + 199 + ], + "leaks": [ + 0, + 2 + ], + "purchases": [ + "Herdhüter", + "Kohlenbeißer" + ], + "roster": [ + 7, + 4 + ], + "seconds": 36.4333333333325, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1716 + ], + "damage": [ + 0, + 375 + ], + "gold": [ + 192, + 171 + ], + "leaks": [ + 0, + 9 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 7, + 6 + ], + "seconds": 36.8999999999992, + "sends": [ + "s02" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1584 + ], + "damage": [ + 0, + 132 + ], + "gold": [ + 193, + 179 + ], + "leaks": [ + 0, + 4 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 8, + 6 + ], + "seconds": 46.5666666666653, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1035 + ], + "damage": [ + 0, + 549 + ], + "gold": [ + 211, + 162 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 9, + 6 + ], + "seconds": 49.9999999999984, + "sends": [ + "s02" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 112 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 157, + 157 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 4 + ], + "seconds": 27.3333333333331, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 142, + 142 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 5 + ], + "seconds": 23.25, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 156, + 156 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 17.6666666666669, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 190, + 190 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 182, + 182 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 6, + 6 + ], + "seconds": 20.7833333333334, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 244, + 244 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Basaltbastion ↑" + ], + "roster": [ + 6, + 6 + ], + "seconds": 24.9666666666665, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "damage": [ + 200, + 0 + ], + "gold": [ + 295, + 139 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "damage": [ + 270, + 0 + ], + "gold": [ + 373, + 112 + ], + "leaks": [ + 10, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "damage": [ + 489, + 0 + ], + "gold": [ + 454, + 150 + ], + "leaks": [ + 11, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 20.0333333333335, + "sends": [], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "damage": [ + 457, + 0 + ], + "gold": [ + 538, + 151 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 20.0666666666668, + "sends": [], + "wave": 4, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "damage": [ + 551, + 0 + ], + "gold": [ + 625, + 161 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 15.3333333333337, + "sends": [], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 304, + 3000 + ], + "damage": [ + 729, + 0 + ], + "gold": [ + 715, + 187 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 18.1166666666669, + "sends": [], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 0, + 3000 + ], + "damage": [ + 304, + 0 + ], + "gold": [ + 715, + 37 + ], + "leaks": [ + 12, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers_ordered": 0 + } + ] + } + ], + "wave_count": 8 +} \ No newline at end of file diff --git a/docs/phase7-QA.md b/docs/phase7-QA.md new file mode 100644 index 0000000..17fcc3a --- /dev/null +++ b/docs/phase7-QA.md @@ -0,0 +1,43 @@ +# Grafikupdate · Prüfprotokoll der Demo 0.7.0 + +Stand: **16. September 2026**. Entwicklung mit Godot `4.7.2.stable.fedora.ed1daf0bf`, Linux-Release mit offiziellem Template `4.7.2.stable.official.ed1daf0bf`. NVIDIA RTX 5060 Ti, Linux, Vulkan Forward+ sowie OpenGL Compatibility. + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | 209 Prüfungen bestanden | +| Drei vollständige Partien mit regulären Ressourcen | 361 Prüfungen bestanden | +| Aus ZIP entpackte Linux-Demo ohne Projektordner, headless | 174 Prüfungen bestanden | +| Entpackte Linux-Demo, Vulkan Forward+ | 182 Prüfungen bestanden; acht Viewport-Aufnahmen | +| Entpackte Linux-Demo, OpenGL-Startskript | 182 Prüfungen bestanden | +| Eingebettetes PCK der Windows-EXE mit Linux-Godot | 174 Prüfungen bestanden | +| Kamera, Fokus, Optionspause, Audio bei 2× | 9 Prüfungen bestanden | +| Geometrie, Hashes, geschlossene Körper, Normalen und Budgets | 55/55 GLBs bestanden, 0 Warnungen; 20 Upgrade-Paare unterscheidbar | +| Godot-Import mit echten Bounds und Geometrie | 55/55 bestanden | +| Eigenständige Blender-Skripte | 9/9 bestanden; bestehende Szene erhalten; native Szene erneut geöffnet | +| ZIP-Pakete | CRC, SHA-256 und Hashes der entpackten Programme stimmen | +| Nativer Windows-Lauf | Nicht durchgeführt; kein Windows-System oder Wine verfügbar | + +Der Pakettest prüft zehn Glutpakt-Rigs und sechs neue Gegner, vollständige Dreiecksübernahme und identische neutrale Bounds. Er prüft entgegengesetzte Beinschritte, unabhängige Instanzen, geteilte Meshes, Audio und Icons. Der neue Modellbetrachter wird über echte V-/Esc-Tasteneingaben geöffnet und geschlossen; Pause, blockierte Leertaste, Modellwechsel, vorherige Pause und Fokuswiederherstellung werden geprüft. Optionsmenü, Kamera und eine vollständige Acht-Wellen-Partie bleiben Bestandteil des Tests. + +Die drei regulären Partien bleiben unverändert: Standard gegen Lernmodus gewinnt Welle 8 mit 3.000 / 1.035 Kern-HP; Standard gegen Standard endet 3.000 / 3.000; leeres Baufeld verliert Welle 7 mit 0 / 3.000. [Balance und Kaufplan](phase7-balance.md), [Abnahmedaten](phase7-verification.json). + +## Leistung + +Ein tatsächlich gerenderter Bosskampf mit 28 Kampfinstanzen, Welle 8 und 2× wurde nach zwei Sekunden Aufwärmen zwölf Sekunden lang gemessen: **143,98 FPS im Mittel**, **6,95 ms mittlere Framezeit**, **8,56 ms 95. Perzentil**, maximal **1.557 Draw Calls**, 54 Audioereignisse. Auflösung 1600 × 960, Vulkan Forward+, NVIDIA RTX 5060 Ti, VSync aktiv. Diese lokale Stichprobe ist keine allgemeine Leistungszusage. [Messdaten](phase7-runtime.json). + +## Reproduktion und Belege + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . res://tools/verify_phase5.tscn -- --phase7 +python3 tools/verify_phase4_glb.py --json +godot --headless --path . --script res://tools/verify_phase4_models.gd +ALSOFT_DRIVERS=null blender --background --factory-startup --python-exit-code 1 --python tools/verify_phase4_standalone.py +godot --path . res://tools/verify_phase6_runtime.tscn -- --phase7 +``` + +Die Datei des Laufzeittests behält ihren alten Namen. Pakettests werden aus `/tmp` mit den entpackten Programmen ausgeführt, ohne Zugriff auf den Projektordner als Spielquelle. Einzelheiten: [Builds](phase7-builds.md). [Protokolle](phase7-logs/), [GLB-Audit](phase7-glb-audit.json), [Paket-Hashes](phase7-package-check.json). + +Acht unveränderte Aufnahmen der exportierten Linux-Demo: [Menü](screenshots/phase7/menu.png), [Optionen](screenshots/phase7/options.png), [Bauphase](screenshots/phase7/build.png), [Kampf](screenshots/phase7/combat.png), [Boss](screenshots/phase7/boss.png), [Sieg](screenshots/phase7/victory.png), [Basaltbastion](screenshots/phase7/model-g04.png), [Sonnenesse](screenshots/phase7/model-g10.png). + +Geprüft wurde die Demo mit automatisierten Eingaben und Sichtprüfung. Menschliche Spieltests stehen aus. Die Modelle bleiben stilisierte Originalumsetzungen der Projektillustrationen; 30 Figuren anderer, noch nicht spielbarer Fraktionen wurden in diesem Grafikupdate nicht verändert. Historischer Vergleich: [Phase-6-QA](phase6-QA.md). diff --git a/docs/phase7-balance.md b/docs/phase7-balance.md new file mode 100644 index 0000000..0012117 --- /dev/null +++ b/docs/phase7-balance.md @@ -0,0 +1,92 @@ +# Glutpakt · Daten und vollständige Testpartien + +Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler. + +## Einheiten + +Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit. + +| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit | +| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- | +| g01 | Kohlenbeißer | 45 | 260 | 17 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s. | +| g02 | Schlackenklaue | 90 | 690 | 44 | 1.2 | Klinge | Schwer | Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s. | +| g03 | Schlackenwacht | 70 | 650 | 11 | 1.2 | Klinge | Schwer | Erste 8 s: 15 % weniger erlittener Schaden. | +| g04 | Basaltbastion | 150 | 1650 | 27 | 1.4 | Klinge | Schwer | Erste 10 s: 25 % weniger Schaden, danach 10 %. | +| g05 | Funkenlanze | 65 | 240 | 24 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: 50 % zusätzlicher Grundschaden. | +| g06 | Glasballiste | 140 | 640 | 65 | 6.5 | Durchschlag | Leicht | Jeder 4. Treffer: 75 % zusätzlicher Grundschaden. | +| g07 | Aschenwerfer | 95 | 310 | 23 | 4.5 | Impuls | Leicht | Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m. | +| g08 | Kraterrufer | 190 | 820 | 58 | 5.0 | Impuls | Schwer | Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m. | +| g09 | Herdhüter | 85 | 420 | 12 | 3.5 | Impuls | Ätherisch | Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden. | +| g10 | Sonnenesse | 170 | 1080 | 30 | 4.0 | Impuls | Ätherisch | Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung. | + +## Wellen + +| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor | +| ---: | --- | --- | ---: | ---: | +| 1 | Erste Risse | 8 × Splitterling | 1.000 | 1.000 | +| 2 | Splitterstrom | 10 × Splitterling | 1.150 | 1.084 | +| 3 | Harte Schalen | 6 × Splitterling, 4 × Schalenläufer | 1.320 | 1.176 | +| 4 | Fäden im Rücken | 8 × Splitterling, 4 × Fadenschütze | 1.510 | 1.276 | +| 5 | Der Bruchhirsch | 1 × Bruchhirsch, 6 × Splitterling | 1.720 | 1.384 | +| 6 | Gepanzerter Vorstoß | 6 × Schalenläufer, 6 × Splitterling | 1.950 | 1.500 | +| 7 | Stimmen aus dem Nebel | 8 × Nebelrest, 4 × Splitterling | 2.200 | 1.624 | +| 8 | Der letzte Riegel | 1 × Riegelkoloss, 2 × Schalenläufer, 3 × Fadenschütze | 2.470 | 1.756 | + +## Standard gegen Lernmodus + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 22.3 | 3000 / 3000 | 0 / 0 | 112 / 177 | 4 / 3 | +| 3 | 32.1 | 3000 / 2733 | 0 / 5 | 156 / 191 | 4 / 3 | +| 4 | 22.1 | 3000 / 2380 | 0 / 11 | 137 / 176 | 5 / 3 | +| 5 | 36.4 | 3000 / 2091 | 0 / 2 | 166 / 199 | 7 / 4 | +| 6 | 36.9 | 3000 / 1716 | 0 / 9 | 192 / 171 | 7 / 6 | +| 7 | 46.6 | 3000 / 1584 | 0 / 4 | 193 / 179 | 8 / 6 | +| 8 | 50.0 | 3000 / 1035 | 0 / 5 | 211 / 162 | 9 / 6 | + +Ergebnis: Front 0 gewinnt. + +## Standard gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 112 / 112 | 4 / 4 | +| 3 | 27.3 | 3000 / 3000 | 0 / 0 | 157 / 157 | 4 / 4 | +| 4 | 23.2 | 3000 / 3000 | 0 / 0 | 142 / 142 | 5 / 5 | +| 5 | 17.7 | 3000 / 3000 | 0 / 0 | 156 / 156 | 5 / 5 | +| 6 | 22.1 | 3000 / 3000 | 0 / 0 | 190 / 190 | 5 / 5 | +| 7 | 20.8 | 3000 / 3000 | 0 / 0 | 182 / 182 | 6 / 6 | +| 8 | 25.0 | 3000 / 3000 | 0 / 0 | 244 / 244 | 6 / 6 | + +Ergebnis: Gleichstand. + +## Leeres Baufeld gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 295 / 139 | 0 / 3 | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 373 / 112 | 0 / 4 | +| 3 | 20.0 | 2041 / 3000 | 11 / 0 | 454 / 150 | 0 / 4 | +| 4 | 20.1 | 1584 / 3000 | 13 / 0 | 538 / 151 | 0 / 5 | +| 5 | 15.3 | 1033 / 3000 | 8 / 0 | 625 / 161 | 0 / 5 | +| 6 | 18.1 | 304 / 3000 | 13 / 0 | 715 / 187 | 0 / 5 | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 715 / 37 | 0 / 5 | + +Ergebnis: Front 1 gewinnt. + +## Nachvollziehbarer Kaufplan gegen den Lernmodus + +Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern. + +| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs | +| ---: | --- | ---: | --- | +| 1 | Schlackenwacht, Funkenlanze, Kohlenbeißer | 0 | | +| 2 | Funkenlanze | 1 | | +| 3 | Schlackenklaue ↑ | 0 | s02 | +| 4 | Funkenlanze | 1 | s01 | +| 5 | Herdhüter, Kohlenbeißer | 0 | s01 | +| 6 | Glasballiste ↑ | 0 | s02 | +| 7 | Glasballiste ↑, Kohlenbeißer | 0 | s01 | +| 8 | Glasballiste ↑, Kohlenbeißer | 0 | s02 | diff --git a/docs/phase7-builds.md b/docs/phase7-builds.md new file mode 100644 index 0000000..2995a97 --- /dev/null +++ b/docs/phase7-builds.md @@ -0,0 +1,42 @@ +# Demo 0.7.0 · Windows und Linux + +## Starten + +Im übergeordneten `dist`-Ordner liegen zwei ZIP-Pakete. Vollständig entpacken. Unter Windows `Saumwacht.exe`, unter Linux `Spielen.sh` oder `Saumwacht.x86_64` starten. Die Programme enthalten ihr PCK; der Projektordner wird nicht benötigt. Bei Vulkan-Problemen startet `Kompatibilitaet.bat` bzw. `Kompatibilitaet.sh` mit OpenGL 3.3. Dieser Modus zeigt dieselbe Geometrie, jedoch ohne SSAO und Glow. + +Die Windows-Demo ist ein nicht signiertes x86-64-GUI-Programm. Sie wird für Windows 10/11 mit Vulkan-fähiger Grafik bereitgestellt. Ein echter Windows-Test steht aus. Die Linux-Demo wurde mit NVIDIA RTX 5060 Ti unter Fedora geprüft; daraus folgt keine Leistungszusage für andere Hardware. + +## Erstellen + +Verwendet werden die offiziellen Release-Templates von [Godot 4.7.2](https://godotengine.org/download/archive/4.7.2-stable/). Die installierte Fedora-Engine und die offiziellen Templates melden denselben Commit `ed1daf0bf`. Godots [Exportdokumentation](https://docs.godotengine.org/en/4.7/tutorials/export/exporting_projects.html) beschreibt das zugrunde liegende Verfahren. + +Die zwei benötigten Dateien aus dem offiziellen TPZ-Archiv liegen unter `assets-source/phase6/export-templates`: + +- `linux_release.x86_64` +- `windows_release_x86_64.exe` +- `version.txt`: `4.7.2.stable` + +Der Quellordner wird durch `.gdignore` nicht in das Spiel aufgenommen. Falls die Templates fehlen, das Standard-Archiv von der oben verlinkten offiziellen Downloadseite beziehen, als ZIP öffnen und nur diese Dateien in den genannten Ordner kopieren. + +```bash +python3 tools/build_demo.py +``` + +`export_presets.cfg` definiert Linux und Windows. Beide nutzen eingebettetes PCK und x86-64. Dokumentation, Entwicklungswerkzeuge, Tests und nicht verwendete UI-/Kartenillustrationen sind ausgeschlossen. Die dynamisch geladenen Assetmanifeste sind ausdrücklich enthalten. Die noch nicht spielbaren Fraktionsmodelle bleiben im Assetkatalog enthalten; die Spielauswahl ist weiterhin Glutpakt. + +Der Build-Schritt schreibt EXE/ELF, ZIPs, Anleitungen, `build-manifest.json`, `SHA256SUMS.txt` und Exportprotokolle in `../dist`. Er benötigt die vorhandenen Lizenzquellen unter `assets-source/phase6/licenses`. + +## Paketprüfung + +```bash +# Außerhalb des Projektordners ausführen: +/path/to/dist/linux/Saumwacht.x86_64 --headless -- --smoke-test +/path/to/dist/linux/Saumwacht.x86_64 -- --smoke-test + +# Prüft Windows-Spieldaten mit der Linux-Engine, nicht den Windows-Prozess: +godot --headless --main-pack /path/to/dist/windows/Saumwacht.exe -- --smoke-test +``` + +Der explizite Prüfmodus testet den neuen Modellbetrachter mit Pause/Fokus/Modellwechsel, hohe Dreieckszahlen, Gelenkgeometrie, unabhängige Instanzen, gebündelte Audio-/Bildassets, Optionspause, Fokus, Kamera, Einstellungsdateien und eine komplette bezahlte Acht-Wellen-Partie. Graphisch speichert er acht unveränderte Viewport-Aufnahmen unter `user://phase7-smoke`, einschließlich zweier Modell-Nahansichten. Ohne `--smoke-test` läuft das normale Spiel. + +Einstellungen liegen in `user://preferences.cfg`: unter Windows normalerweise `%APPDATA%/Godot/app_userdata/Saumwacht · Glutpakt`, unter Linux `~/.local/share/godot/app_userdata/Saumwacht · Glutpakt`. Der Test verwendet für seinen Einstellungs-Rundlauf eine eigene temporäre Datei und stellt die vorherigen Einstellungen wieder her. diff --git a/docs/phase7-glb-audit.json b/docs/phase7-glb-audit.json new file mode 100644 index 0000000..01130a4 --- /dev/null +++ b/docs/phase7-glb-audit.json @@ -0,0 +1,4431 @@ +{ + "asset_count": 55, + "errors": [], + "assets": [ + { + "id": "g01", + "file": "unit_g01.glb", + "errors": [], + "warnings": [], + "triangles": 51844, + "mesh_parts": 131, + "primitives": 131, + "vertices": 40435, + "closed_meshes": 131, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g02", + "file": "unit_g02.glb", + "errors": [], + "warnings": [], + "triangles": 52056, + "mesh_parts": 133, + "primitives": 133, + "vertices": 40509, + "closed_meshes": 133, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g03", + "file": "unit_g03.glb", + "errors": [], + "warnings": [], + "triangles": 42352, + "mesh_parts": 119, + "primitives": 119, + "vertices": 31773, + "closed_meshes": 119, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g04", + "file": "unit_g04.glb", + "errors": [], + "warnings": [], + "triangles": 61340, + "mesh_parts": 220, + "primitives": 220, + "vertices": 45815, + "closed_meshes": 220, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g05", + "file": "unit_g05.glb", + "errors": [], + "warnings": [], + "triangles": 38388, + "mesh_parts": 118, + "primitives": 118, + "vertices": 29292, + "closed_meshes": 118, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderFin", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderFin", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ChestStoneL", + "Body_ChestStoneR", + "Body_CuirassL", + "Body_CuirassR", + "Body_EmberHeart", + "Body_Spine", + "Head_Crest", + "Head_Helmet", + "Head_Neck", + "Head_Visor", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar10", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceEmber", + "Weapon_LanceShaft", + "Weapon_SpearEdge1", + "Weapon_SpearEdge_1", + "Weapon_SpearHead" + ] + }, + { + "id": "g06", + "file": "unit_g06.glb", + "errors": [], + "warnings": [], + "triangles": 26884, + "mesh_parts": 85, + "primitives": 85, + "vertices": 18642, + "closed_meshes": 85, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrankInsetL", + "Body_CrankInsetR", + "Body_CrankL", + "Body_CrankR", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Body_Gearbox", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoltHead", + "Weapon_CentralBolt", + "Weapon_DrawCableL", + "Weapon_DrawCableR", + "Weapon_GlassLimbL", + "Weapon_GlassLimbR", + "Weapon_LimbClampL", + "Weapon_LimbClampR", + "Weapon_LimbEdgeL", + "Weapon_LimbEdgeR", + "Weapon_RailL", + "Weapon_RailR", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5", + "Weapon_RailTrimL", + "Weapon_RailTrimR", + "Weapon_RearHousing", + "Weapon_RearTrim" + ] + }, + { + "id": "g07", + "file": "unit_g07.glb", + "errors": [], + "warnings": [], + "triangles": 51284, + "mesh_parts": 128, + "primitives": 128, + "vertices": 41969, + "closed_meshes": 128, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "Weapon_EmberBoulder", + "Weapon_LavaPool" + ] + }, + { + "id": "g08", + "file": "unit_g08.glb", + "errors": [], + "warnings": [], + "triangles": 46922, + "mesh_parts": 123, + "primitives": 123, + "vertices": 37253, + "closed_meshes": 123, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "Weapon_LavaPool" + ] + }, + { + "id": "g09", + "file": "unit_g09.glb", + "errors": [], + "warnings": [], + "triangles": 54596, + "mesh_parts": 173, + "primitives": 173, + "vertices": 39482, + "closed_meshes": 173, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone10", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_HearthBack", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Body_OvenDark", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Head_Chimney", + "Head_ChimneyCap", + "Head_ChimneyRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "g10", + "file": "unit_g10.glb", + "errors": [], + "warnings": [], + "triangles": 66734, + "mesh_parts": 223, + "primitives": 223, + "vertices": 47050, + "closed_meshes": 223, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_HearthBack", + "Body_MantleL", + "Body_MantleR", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_OvenDark", + "Body_SolarStream", + "Body_SunFrame", + "Body_SunHeart", + "Body_SunSocket", + "Body_TabardL", + "Body_TabardR", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "m01", + "file": "unit_m01.glb", + "errors": [], + "warnings": [], + "triangles": 1284, + "mesh_parts": 42, + "primitives": 42, + "vertices": 2424, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Upper", + "Body_Belt", + "Body_Chimney", + "Body_ChimneyLip", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_PressureGauge", + "Body_RoundKettle", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m02", + "file": "unit_m02.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2552, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Pauldron", + "ArmL_Shield_Face", + "ArmL_Shield_Rim", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Pauldron", + "ArmR_Shield_Face", + "ArmR_Shield_Rim", + "ArmR_Upper", + "Body_CeramicChest_Face", + "Body_CeramicChest_Rim", + "Body_HeavyChest", + "Body_PressureTankL", + "Body_PressureTankR", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemL", + "Body_ValveStemR", + "Body_ValveWheelL", + "Body_ValveWheelR", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m03", + "file": "unit_m03.glb", + "errors": [], + "warnings": [], + "triangles": 932, + "mesh_parts": 43, + "primitives": 43, + "vertices": 1776, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ] + }, + { + "id": "m04", + "file": "unit_m04.glb", + "errors": [], + "warnings": [], + "triangles": 1398, + "mesh_parts": 60, + "primitives": 60, + "vertices": 2600, + "closed_meshes": 60, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "ArmL1_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "ArmL2_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "ArmR1_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "ArmR2_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL1_Blade0", + "WeaponL2_Blade0", + "WeaponR0_Blade0", + "WeaponR1_Blade0", + "WeaponR2_Blade0" + ] + }, + { + "id": "m05", + "file": "unit_m05.glb", + "errors": [], + "warnings": [], + "triangles": 1148, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2192, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Head_Scope", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m06", + "file": "unit_m06.glb", + "errors": [], + "warnings": [], + "triangles": 1432, + "mesh_parts": 66, + "primitives": 66, + "vertices": 2730, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m07", + "file": "unit_m07.glb", + "errors": [], + "warnings": [], + "triangles": 740, + "mesh_parts": 27, + "primitives": 27, + "vertices": 1403, + "closed_meshes": 27, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_ResonatorHousing0", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston" + ] + }, + { + "id": "m08", + "file": "unit_m08.glb", + "errors": [], + "warnings": [], + "triangles": 1316, + "mesh_parts": 50, + "primitives": 50, + "vertices": 2464, + "closed_meshes": 50, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_HousingLatch1_1", + "Body_HousingLatch1__1", + "Body_ResonatorHousing0", + "Body_ResonatorHousing1", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_DiscPiston0", + "Weapon_DiscPiston1", + "Weapon_ImpactDisc0", + "Weapon_ImpactDisc1" + ] + }, + { + "id": "m09", + "file": "unit_m09.glb", + "errors": [], + "warnings": [], + "triangles": 1160, + "mesh_parts": 51, + "primitives": 51, + "vertices": 2146, + "closed_meshes": 51, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_PendulumBob", + "Body_PendulumStem", + "Body_Waist", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "m10", + "file": "unit_m10.glb", + "errors": [], + "warnings": [], + "triangles": 946, + "mesh_parts": 49, + "primitives": 49, + "vertices": 1828, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Upper", + "Body_Coat", + "Body_CoatGoldL", + "Body_CoatGoldR", + "Body_CreamStoleL", + "Body_CreamStoleR", + "Body_PendulumBob", + "Body_PendulumOpening", + "Body_PendulumStem", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "n01", + "file": "unit_n01.glb", + "errors": [], + "warnings": [], + "triangles": 1132, + "mesh_parts": 16, + "primitives": 16, + "vertices": 3232, + "closed_meshes": 16, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Claw", + "WeaponR_Claw" + ] + }, + { + "id": "n02", + "file": "unit_n02.glb", + "errors": [], + "warnings": [], + "triangles": 1156, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3304, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1" + ] + }, + { + "id": "n03", + "file": "unit_n03.glb", + "errors": [], + "warnings": [], + "triangles": 934, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2688, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Sickle", + "WeaponR_Sickle" + ] + }, + { + "id": "n04", + "file": "unit_n04.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3932, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CrescentCrown", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_ShearLoopLower", + "Weapon_ShearLoopUpper", + "Weapon_ShearLower", + "Weapon_ShearPivot", + "Weapon_ShearUpper" + ] + }, + { + "id": "n05", + "file": "unit_n05.glb", + "errors": [], + "warnings": [], + "triangles": 1118, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2986, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip" + ] + }, + { + "id": "n06", + "file": "unit_n06.glb", + "errors": [], + "warnings": [], + "triangles": 1498, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3844, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_HornArchL", + "Weapon_HornArchR", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ] + }, + { + "id": "n07", + "file": "unit_n07.glb", + "errors": [], + "warnings": [], + "triangles": 1274, + "mesh_parts": 15, + "primitives": 15, + "vertices": 3354, + "closed_meshes": 15, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_BellRim", + "Weapon_Clapper", + "Weapon_ClapperStem", + "Weapon_HangingBell" + ] + }, + { + "id": "n08", + "file": "unit_n08.glb", + "errors": [], + "warnings": [], + "triangles": 1482, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3958, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Sickle", + "ArmR_Sickle", + "Body_ArchMask", + "Body_ArchMask_Eye1", + "Body_ArchMask_Eye_1", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Body_CathedralShell", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CentralSpire", + "Head_SpireL", + "Head_SpireR", + "Weapon_Clapper", + "Weapon_ClapperChain" + ] + }, + { + "id": "n09", + "file": "unit_n09.glb", + "errors": [], + "warnings": [], + "triangles": 1314, + "mesh_parts": 24, + "primitives": 24, + "vertices": 3740, + "closed_meshes": 24, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "n10", + "file": "unit_n10.glb", + "errors": [], + "warnings": [], + "triangles": 1734, + "mesh_parts": 40, + "primitives": 40, + "vertices": 4872, + "closed_meshes": 40, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirHorn1_1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn2_1", + "Head_ChoirHorn2__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Mouth", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp0", + "Head_ChoirWisp1", + "Head_ChoirWisp2", + "Head_CurledHood", + "Head_GreatHorn1", + "Head_GreatHorn_1", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "w01", + "file": "unit_w01.glb", + "errors": [], + "warnings": [], + "triangles": 576, + "mesh_parts": 36, + "primitives": 36, + "vertices": 1460, + "closed_meshes": 36, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BarkPlate0", + "Body_BarkPlate1", + "Body_BarkPlate2", + "Body_BarkPlate3", + "Body_BarkPlate4", + "Body_BarkPlate5", + "Body_BarkPlate6", + "Body_Flower_Heart", + "Body_Flower_Petal0", + "Body_Flower_Petal1", + "Body_Flower_Petal2", + "Body_Flower_Petal3", + "Body_Flower_Petal4", + "Body_MossCore", + "Body_Thorn0", + "Body_Thorn1", + "Body_Thorn2", + "Body_Thorn3", + "Body_Thorn4", + "Body_Thorn5", + "Body_Thorn6", + "Head_Eye1", + "Head_EyeSlit", + "Head_Eye_1", + "Head_Leaf1", + "Head_Leaf_1", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Root0", + "Leg_Root1", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2" + ] + }, + { + "id": "w02", + "file": "unit_w02.glb", + "errors": [], + "warnings": [], + "triangles": 1140, + "mesh_parts": 55, + "primitives": 55, + "vertices": 3172, + "closed_meshes": 55, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BraidedVine0", + "Body_BraidedVine1", + "Body_BraidedVine2", + "Body_VineMass", + "Head_GreenLipL", + "Head_GreenLipR", + "Head_JawFlowerL_Heart", + "Head_JawFlowerL_Petal0", + "Head_JawFlowerL_Petal1", + "Head_JawFlowerL_Petal2", + "Head_JawFlowerL_Petal3", + "Head_JawFlowerL_Petal4", + "Head_JawFlowerR_Heart", + "Head_JawFlowerR_Petal0", + "Head_JawFlowerR_Petal1", + "Head_JawFlowerR_Petal2", + "Head_JawFlowerR_Petal3", + "Head_JawFlowerR_Petal4", + "Head_JawLeafL", + "Head_JawLeafR", + "Head_LowerFangL0", + "Head_LowerFangL1", + "Head_LowerFangL2", + "Head_LowerFangR0", + "Head_LowerFangR1", + "Head_LowerFangR2", + "Head_LowerJaw", + "Head_MouthShadow", + "Head_UpperFangL0", + "Head_UpperFangL1", + "Head_UpperFangL2", + "Head_UpperFangR0", + "Head_UpperFangR1", + "Head_UpperFangR2", + "Head_UpperJaw", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w03", + "file": "unit_w03.glb", + "errors": [], + "warnings": [], + "triangles": 848, + "mesh_parts": 49, + "primitives": 49, + "vertices": 2204, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CorkTile0_0", + "Body_CorkTile0_1", + "Body_CorkTile0_2", + "Body_CorkTile0_3", + "Body_CorkTile0_4", + "Body_CorkTile1_0", + "Body_CorkTile1_1", + "Body_CorkTile1_2", + "Body_CorkTile1_3", + "Body_CorkTile1_4", + "Body_CorkTile2_0", + "Body_CorkTile2_1", + "Body_CorkTile2_2", + "Body_CorkTile2_3", + "Body_CorkTile2_4", + "Body_CrownLeaf", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_MossDome", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w04", + "file": "unit_w04.glb", + "errors": [], + "warnings": [], + "triangles": 1760, + "mesh_parts": 55, + "primitives": 55, + "vertices": 3852, + "closed_meshes": 55, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_LogShield0_Bark", + "Body_LogShield0_Cut", + "Body_LogShield0_GrowthRing0", + "Body_LogShield0_GrowthRing1", + "Body_LogShield1_Bark", + "Body_LogShield1_Cut", + "Body_LogShield1_GrowthRing0", + "Body_LogShield1_GrowthRing1", + "Body_LogShield2_Bark", + "Body_LogShield2_Cut", + "Body_LogShield2_GrowthRing0", + "Body_LogShield2_GrowthRing1", + "Body_LogShield3_Bark", + "Body_LogShield3_Cut", + "Body_LogShield3_GrowthRing0", + "Body_LogShield3_GrowthRing1", + "Body_LogShield4_Bark", + "Body_LogShield4_Cut", + "Body_LogShield4_GrowthRing0", + "Body_LogShield4_GrowthRing1", + "Body_MossDome", + "Head_Sprout1", + "Head_Sprout_1", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w05", + "file": "unit_w05.glb", + "errors": [], + "warnings": [], + "triangles": 878, + "mesh_parts": 35, + "primitives": 35, + "vertices": 2372, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BroadLeaf1", + "Body_BroadLeaf_1", + "Body_ClimbingVine", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_TwistedStem", + "Head_SeedLauncher_Cup", + "Head_SeedLauncher_LipLeaf1", + "Head_SeedLauncher_LipLeaf_1", + "Head_SeedLauncher_Seed", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2" + ] + }, + { + "id": "w06", + "file": "unit_w06.glb", + "errors": [], + "warnings": [], + "triangles": 1178, + "mesh_parts": 53, + "primitives": 53, + "vertices": 3072, + "closed_meshes": 53, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BroadLeaf1", + "Body_BroadLeaf_1", + "Body_ClimbingVine", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_TwistedStem", + "Head_SeedLauncher_ConeScale0_0", + "Head_SeedLauncher_ConeScale0_1", + "Head_SeedLauncher_ConeScale0_2", + "Head_SeedLauncher_ConeScale0_3", + "Head_SeedLauncher_ConeScale0_4", + "Head_SeedLauncher_ConeScale1_0", + "Head_SeedLauncher_ConeScale1_1", + "Head_SeedLauncher_ConeScale1_2", + "Head_SeedLauncher_ConeScale1_3", + "Head_SeedLauncher_ConeScale1_4", + "Head_SeedLauncher_ConeScale2_0", + "Head_SeedLauncher_ConeScale2_1", + "Head_SeedLauncher_ConeScale2_2", + "Head_SeedLauncher_ConeScale2_3", + "Head_SeedLauncher_ConeScale2_4", + "Head_SeedLauncher_Cup", + "Head_SeedLauncher_Seed", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w07", + "file": "unit_w07.glb", + "errors": [], + "warnings": [], + "triangles": 1056, + "mesh_parts": 43, + "primitives": 43, + "vertices": 2568, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_ChaliceTrunk", + "Body_SideFungus1_MossFringe0", + "Body_SideFungus1_MossFringe1", + "Body_SideFungus1_MossFringe2", + "Body_SideFungus1_MossRim", + "Body_SideFungus1_PinkCup", + "Body_SideFungus_1_MossFringe0", + "Body_SideFungus_1_MossFringe1", + "Body_SideFungus_1_MossFringe2", + "Body_SideFungus_1_MossRim", + "Body_SideFungus_1_PinkCup", + "Head_SporeChalice_MossFringe0", + "Head_SporeChalice_MossFringe1", + "Head_SporeChalice_MossFringe2", + "Head_SporeChalice_MossFringe3", + "Head_SporeChalice_MossFringe4", + "Head_SporeChalice_MossFringe5", + "Head_SporeChalice_MossRim", + "Head_SporeChalice_PinkCup", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2", + "Weapon_Spore0", + "Weapon_Spore1", + "Weapon_Spore2", + "Weapon_Spore3" + ] + }, + { + "id": "w08", + "file": "unit_w08.glb", + "errors": [], + "warnings": [], + "triangles": 1634, + "mesh_parts": 62, + "primitives": 62, + "vertices": 3736, + "closed_meshes": 62, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_FungalTrunk0", + "Body_FungalTrunk1", + "Body_FungalTrunk2", + "Body_SmallFungus0_MossFringe0", + "Body_SmallFungus0_MossFringe1", + "Body_SmallFungus0_MossFringe2", + "Body_SmallFungus0_MossRim", + "Body_SmallFungus0_PinkCup", + "Body_SmallFungus1_MossFringe0", + "Body_SmallFungus1_MossFringe1", + "Body_SmallFungus1_MossFringe2", + "Body_SmallFungus1_MossRim", + "Body_SmallFungus1_PinkCup", + "Body_SmallFungus2_MossFringe0", + "Body_SmallFungus2_MossFringe1", + "Body_SmallFungus2_MossFringe2", + "Body_SmallFungus2_MossRim", + "Body_SmallFungus2_PinkCup", + "Head_FungalTier0_MossFringe0", + "Head_FungalTier0_MossFringe1", + "Head_FungalTier0_MossFringe2", + "Head_FungalTier0_MossFringe3", + "Head_FungalTier0_MossFringe4", + "Head_FungalTier0_MossFringe5", + "Head_FungalTier0_MossRim", + "Head_FungalTier0_PinkCup", + "Head_FungalTier1_MossFringe0", + "Head_FungalTier1_MossFringe1", + "Head_FungalTier1_MossFringe2", + "Head_FungalTier1_MossFringe3", + "Head_FungalTier1_MossFringe4", + "Head_FungalTier1_MossFringe5", + "Head_FungalTier1_MossRim", + "Head_FungalTier1_PinkCup", + "Head_FungalTier2_MossFringe0", + "Head_FungalTier2_MossFringe1", + "Head_FungalTier2_MossFringe2", + "Head_FungalTier2_MossFringe3", + "Head_FungalTier2_MossFringe4", + "Head_FungalTier2_MossFringe5", + "Head_FungalTier2_MossRim", + "Head_FungalTier2_PinkCup", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w09", + "file": "unit_w09.glb", + "errors": [], + "warnings": [], + "triangles": 812, + "mesh_parts": 31, + "primitives": 31, + "vertices": 2138, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Arm_BasinVine1", + "Arm_BasinVine_1", + "Body_LivingTrunk", + "Body_WindingVine", + "Head_Flower_Heart", + "Head_Flower_Petal0", + "Head_Flower_Petal1", + "Head_Flower_Petal2", + "Head_Flower_Petal3", + "Head_Flower_Petal4", + "Head_LeafCrown0", + "Head_LeafCrown1", + "Head_LeafCrown2", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Weapon_DewOrb", + "Weapon_LeafBasin", + "Weapon_Water" + ] + }, + { + "id": "w10", + "file": "unit_w10.glb", + "errors": [], + "warnings": [], + "triangles": 1290, + "mesh_parts": 59, + "primitives": 59, + "vertices": 3458, + "closed_meshes": 59, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Arm_BasinVine1", + "Arm_BasinVine_1", + "Body_Blossom0_Heart", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom1_Heart", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom2_Heart", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom3_Heart", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_FrontVine1", + "Body_FrontVine_1", + "Body_SpringArch1", + "Body_SpringArch_1", + "Head_CanopyLeaf0", + "Head_CanopyLeaf1", + "Head_CanopyLeaf2", + "Head_CanopyLeaf3", + "Head_CanopyLeaf4", + "Head_CanopyLeaf5", + "Head_CanopyLeaf6", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2", + "Weapon_LeafBasin", + "Weapon_Water" + ] + }, + { + "id": "s01", + "file": "unit_s01.glb", + "errors": [], + "warnings": [], + "triangles": 10340, + "mesh_parts": 34, + "primitives": 34, + "vertices": 8466, + "closed_meshes": 34, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_DiagonalBelt", + "Body_LeatherCuirass", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Scarf", + "Body_SplitCoat1", + "Body_SplitCoat_1", + "Body_TornScarf1", + "Body_TornScarf_1", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_Bolt", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_CrossbowStock", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "s02", + "file": "unit_s02.glb", + "errors": [], + "warnings": [], + "triangles": 12040, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9256, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Corner10_4", + "Weapon_Corner11_16", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_ShieldBoss", + "Weapon_ShieldSpine", + "Weapon_TowerShield_Face", + "Weapon_TowerShield_Rim" + ] + }, + { + "id": "s03", + "file": "unit_s03.glb", + "errors": [], + "warnings": [], + "triangles": 7832, + "mesh_parts": 19, + "primitives": 19, + "vertices": 6089, + "closed_meshes": 19, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_CreamStole1", + "Body_CreamStole_1", + "Body_LongRobe", + "Body_RaggedCloak1", + "Body_RaggedCloak_1", + "Body_Scarf", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "Weapon_Trumpet" + ] + }, + { + "id": "s04", + "file": "unit_s04.glb", + "errors": [], + "warnings": [], + "triangles": 10458, + "mesh_parts": 35, + "primitives": 35, + "vertices": 8062, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Haft", + "Weapon_Head", + "Weapon_TriangleInset", + "Weapon_TriangleRim", + "Weapon_Wedge" + ] + }, + { + "id": "s05", + "file": "unit_s05.glb", + "errors": [], + "warnings": [], + "triangles": 10440, + "mesh_parts": 31, + "primitives": 31, + "vertices": 8279, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_HipRag1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_HollowRib_1", + "Body_RiftEdge1", + "Body_RiftEdge_1", + "Body_TornCloth1", + "Body_TornCloth_1", + "Head_Antler1", + "Head_Antler_1", + "Head_FacelessHelm", + "Head_InnerHorn1", + "Head_InnerHorn_1", + "Head_MintCrack", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_RiftLight", + "Weapon_RiftOrb" + ] + }, + { + "id": "worker", + "file": "worker.glb", + "errors": [], + "warnings": [], + "triangles": 15624, + "mesh_parts": 28, + "primitives": 28, + "vertices": 13116, + "closed_meshes": 28, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Hand", + "ArmL_Shoulder", + "ArmR_Hand", + "ArmR_Shoulder", + "Body_Apron", + "Body_ApronPocket", + "Body_ApronStrap1", + "Body_ApronStrap_1", + "Body_Buckle1", + "Body_Buckle_1", + "Body_Clay", + "Head_ClayFace", + "Head_Eye1", + "Head_EyeSocket1", + "Head_EyeSocket_1", + "Head_Eye_1", + "Head_Hood", + "Head_HoodEdge", + "LegL_Foot", + "LegR_Foot", + "Weapon_CollectedSpark", + "Weapon_CollectorProng1", + "Weapon_CollectorProng_1", + "Weapon_CollectorStaff", + "Weapon_LanternCap0_27", + "Weapon_LanternCap0_53", + "Weapon_LanternGlass", + "Weapon_LanternHandle" + ] + }, + { + "id": "map_lane_segment", + "file": "map_lane_segment.glb", + "errors": [], + "warnings": [], + "triangles": 10700, + "mesh_parts": 45, + "primitives": 45, + "vertices": 8523, + "closed_meshes": 45, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeCap1_0", + "Body_EdgeCap1_1", + "Body_EdgeCap1_2", + "Body_EdgeCap1_3", + "Body_EdgeCap_1_0", + "Body_EdgeCap_1_1", + "Body_EdgeCap_1_2", + "Body_EdgeCap_1_3", + "Body_EdgeStone1_0", + "Body_EdgeStone1_1", + "Body_EdgeStone1_2", + "Body_EdgeStone1_3", + "Body_EdgeStone_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeStone_1_3", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_LRetainingLip", + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LightGlass1_0", + "Body_LightGlass1_1", + "Body_LightGlass_1_0", + "Body_LightGlass_1_1", + "Body_LightRecess1_0", + "Body_LightRecess1_1", + "Body_LightRecess_1_0", + "Body_LightRecess_1_1", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Body_RRetainingLip" + ] + }, + { + "id": "core_team0", + "file": "core_team0.glb", + "errors": [], + "warnings": [], + "triangles": 9728, + "mesh_parts": 30, + "primitives": 30, + "vertices": 7438, + "closed_meshes": 30, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_CoreEffect", + "Arm_CradleClasp_0", + "Arm_CradleClasp_1", + "Arm_CradleClasp_2", + "Arm_CradleClasp_3", + "Arm_Cradle_0", + "Arm_Cradle_1", + "Arm_Cradle_2", + "Arm_Cradle_3", + "Body_BrassPlinthRim", + "Body_CoreCrystal", + "Body_CorePlinth", + "Body_CradleStep", + "Body_OuterRim", + "Body_PlinthArmor0", + "Body_PlinthArmor1", + "Body_PlinthArmor2", + "Body_PlinthArmor3", + "Body_PlinthArmor4", + "Body_PlinthArmor5", + "Body_PlinthArmor6", + "Body_PlinthArmor7", + "Body_PlinthGold0", + "Body_PlinthGold1", + "Body_PlinthGold2", + "Body_PlinthGold3", + "Body_PlinthGold4", + "Body_PlinthGold5", + "Body_PlinthGold6", + "Body_PlinthGold7", + "Team_Circle" + ] + }, + { + "id": "core_team1", + "file": "core_team1.glb", + "errors": [], + "warnings": [], + "triangles": 9076, + "mesh_parts": 32, + "primitives": 32, + "vertices": 7093, + "closed_meshes": 32, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_CoreEffect", + "Arm_CradleClasp_0", + "Arm_CradleClasp_1", + "Arm_CradleClasp_2", + "Arm_CradleClasp_3", + "Arm_Cradle_0", + "Arm_Cradle_1", + "Arm_Cradle_2", + "Arm_Cradle_3", + "Body_BrassPlinthRim", + "Body_CoreCrystal", + "Body_CorePlinth", + "Body_CradleStep", + "Body_OuterRim", + "Body_PlinthArmor0", + "Body_PlinthArmor1", + "Body_PlinthArmor2", + "Body_PlinthArmor3", + "Body_PlinthArmor4", + "Body_PlinthArmor5", + "Body_PlinthArmor6", + "Body_PlinthArmor7", + "Body_PlinthGold0", + "Body_PlinthGold1", + "Body_PlinthGold2", + "Body_PlinthGold3", + "Body_PlinthGold4", + "Body_PlinthGold5", + "Body_PlinthGold6", + "Body_PlinthGold7", + "Team_Triangle_0", + "Team_Triangle_1", + "Team_Triangle_2" + ] + }, + { + "id": "e01", + "file": "enemy_e01.glb", + "errors": [], + "warnings": [], + "triangles": 11984, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9859, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e02", + "file": "enemy_e02.glb", + "errors": [], + "warnings": [], + "triangles": 12936, + "mesh_parts": 42, + "primitives": 42, + "vertices": 10343, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Body_Spine0", + "Body_Spine1", + "Body_Spine2", + "Body_Spine3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e03", + "file": "enemy_e03.glb", + "errors": [], + "warnings": [], + "triangles": 22774, + "mesh_parts": 69, + "primitives": 69, + "vertices": 17771, + "closed_meshes": 69, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_RiftHalo", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull" + ] + }, + { + "id": "e04", + "file": "enemy_e04.glb", + "errors": [], + "warnings": [], + "triangles": 36000, + "mesh_parts": 110, + "primitives": 110, + "vertices": 27851, + "closed_meshes": 110, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_Arrow", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "e07", + "file": "enemy_e07.glb", + "errors": [], + "warnings": [], + "triangles": 16144, + "mesh_parts": 49, + "primitives": 49, + "vertices": 13447, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "Body_DeerCore", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_Tail", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_AntlerR", + "Head_EyeL", + "Head_EyeR", + "Head_Muzzle", + "Head_Neck", + "Head_Nose", + "Head_Skull", + "LegL0_ClovenLine", + "LegL0_Hoof", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_ClovenLine", + "LegL1_Hoof", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Upper", + "LegR0_ClovenLine", + "LegR0_Hoof", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_ClovenLine", + "LegR1_Hoof", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Upper" + ] + }, + { + "id": "e08", + "file": "enemy_e08.glb", + "errors": [], + "warnings": [], + "triangles": 61816, + "mesh_parts": 222, + "primitives": 222, + "vertices": 46057, + "closed_meshes": 222, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_RiftHorn1", + "Body_RiftHorn_1", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + } + ], + "upgrade_pairs": [ + { + "base": "g01", + "upgrade": "g02", + "structurally_distinct": true + }, + { + "base": "g03", + "upgrade": "g04", + "structurally_distinct": true + }, + { + "base": "g05", + "upgrade": "g06", + "structurally_distinct": true + }, + { + "base": "g07", + "upgrade": "g08", + "structurally_distinct": true + }, + { + "base": "g09", + "upgrade": "g10", + "structurally_distinct": true + }, + { + "base": "m01", + "upgrade": "m02", + "structurally_distinct": true + }, + { + "base": "m03", + "upgrade": "m04", + "structurally_distinct": true + }, + { + "base": "m05", + "upgrade": "m06", + "structurally_distinct": true + }, + { + "base": "m07", + "upgrade": "m08", + "structurally_distinct": true + }, + { + "base": "m09", + "upgrade": "m10", + "structurally_distinct": true + }, + { + "base": "n01", + "upgrade": "n02", + "structurally_distinct": true + }, + { + "base": "n03", + "upgrade": "n04", + "structurally_distinct": true + }, + { + "base": "n05", + "upgrade": "n06", + "structurally_distinct": true + }, + { + "base": "n07", + "upgrade": "n08", + "structurally_distinct": true + }, + { + "base": "n09", + "upgrade": "n10", + "structurally_distinct": true + }, + { + "base": "w01", + "upgrade": "w02", + "structurally_distinct": true + }, + { + "base": "w03", + "upgrade": "w04", + "structurally_distinct": true + }, + { + "base": "w05", + "upgrade": "w06", + "structurally_distinct": true + }, + { + "base": "w07", + "upgrade": "w08", + "structurally_distinct": true + }, + { + "base": "w09", + "upgrade": "w10", + "structurally_distinct": true + } + ], + "passed": true, + "warning_count": 0 +} diff --git a/docs/phase7-logs/compat-graphical.log b/docs/phase7-logs/compat-graphical.log new file mode 100644 index 0000000..7b870d1 --- /dev/null +++ b/docs/phase7-logs/compat-graphical.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 182 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase7-compat/godot/app_userdata/Saumwacht · Glutpakt/phase7-smoke diff --git a/docs/phase7-logs/godot-models.log b/docs/phase7-logs/godot-models.log new file mode 100644 index 0000000..f0f60da --- /dev/null +++ b/docs/phase7-logs/godot-models.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: Phase 4 models 55/55; 55 entries checked, 0 errors. diff --git a/docs/phase7-logs/graphical-smoke.log b/docs/phase7-logs/graphical-smoke.log new file mode 100644 index 0000000..1f3150d --- /dev/null +++ b/docs/phase7-logs/graphical-smoke.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 182 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase7-smoke diff --git a/docs/phase7-logs/linux-graphical.log b/docs/phase7-logs/linux-graphical.log new file mode 100644 index 0000000..9f0c6f2 --- /dev/null +++ b/docs/phase7-logs/linux-graphical.log @@ -0,0 +1,5 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPORT_SMOKE_PASS: 182 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase7-smoke diff --git a/docs/phase7-logs/linux-headless.log b/docs/phase7-logs/linux-headless.log new file mode 100644 index 0000000..dbd21d4 --- /dev/null +++ b/docs/phase7-logs/linux-headless.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 174 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase7-linux/godot/app_userdata/Saumwacht · Glutpakt/phase7-smoke diff --git a/docs/phase7-logs/matches.log b/docs/phase7-logs/matches.log new file mode 100644 index 0000000..43e94c7 --- /dev/null +++ b/docs/phase7-logs/matches.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RUNTIME_BATCHING: 3436 original parts -> 287 material surfaces across catalog assets +SLICE_MATCH: Standard gegen Lernmodus; wave 8; outcome 0; cores [3000, 1035] +SLICE_MATCH: Standard gegen Standard; wave 8; outcome -1; cores [3000, 3000] +SLICE_MATCH: Leeres Baufeld gegen Standard; wave 7; outcome 1; cores [0, 3000] +PHASE5_PASS: 361 checks; 3 real-budget matches; 0 failures diff --git a/docs/phase7-logs/rules.log b/docs/phase7-logs/rules.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase7-logs/rules.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase7-logs/runtime.log b/docs/phase7-logs/runtime.log new file mode 100644 index 0000000..8783142 --- /dev/null +++ b/docs/phase7-logs/runtime.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +PHASE6_RUNTIME: {"audio_events":54,"checks":9,"device":"NVIDIA GeForce RTX 5060 Ti","engine":"4.7.2-stable (fedora)","failures":[],"frames":1728,"max_draw_calls":1557,"mean_fps":143.979926798539,"mean_frame_ms":6.94541261574073,"p95_frame_ms":8.556,"renderer":"forward_plus","sample_seconds":12,"speed":2,"units_at_start":28,"viewport":"(1600.0, 960.0)","wave":8} diff --git a/docs/phase7-logs/standalone-audit.log b/docs/phase7-logs/standalone-audit.log new file mode 100644 index 0000000..b799b0d --- /dev/null +++ b/docs/phase7-logs/standalone-audit.log @@ -0,0 +1,1724 @@ +00:00.016 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.016 color_management | Using fallback mode for management +/tmp/saumwacht-standalone-owe57vwa/scripts/create_melee.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:13:33 | INFO: Starting glTF 2.0 export +20:13:33 | INFO: Extracting primitive: ArmL0_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL0_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL0_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL0_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL1_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL1_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL1_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL1_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL2_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL2_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL2_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL2_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmL_Shoulder_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR0_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR0_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR0_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR0_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR1_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR1_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR1_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR1_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR2_Housing_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR2_Pivot_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR2_Pivot_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR2_Rod_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: ArmR_Shoulder_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Body_Breastplate_Face_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Body_Breastplate_Rim_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Body_HipPlateL_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Body_HipPlateR_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Body_Waist_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Head_Eye1_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Head_Face_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_AnkleGold_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Greave_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Knee_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Knee_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Piston_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Shin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_ThighArmor_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Toe0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg0_Toe1_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_AnkleGold_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Greave_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Knee_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Knee_Pin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Piston_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Shin_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_ThighArmor_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Toe0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: Leg1_Toe1_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponL0_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponL1_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponL2_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponR0_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponR1_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Extracting primitive: WeaponR2_Blade0_Mesh +20:13:33 | INFO: Primitives created: 1 +20:13:33 | INFO: Finished glTF 2.0 export in 0.0602724552154541 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_tank.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-owe57vwa/scripts/create_tank.py:525: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED m04: 1398 triangles, 60 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_m04.glb +STANDALONE_PASS: m04 +20:13:36 | INFO: Starting glTF 2.0 export +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_BorderL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_BorderR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_BottomGold_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_CenterGold1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_SeamL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_SeamR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_SpineGold_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_Fire_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_FireHeart_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Finished glTF 2.0 export in 0.2728698253631592 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_ranged.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED g04: 61340 triangles, 220 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_g04.glb +STANDALONE_PASS: g04 +20:13:36 | INFO: Starting glTF 2.0 export +20:13:36 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ClimbingVine_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Heart_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Heart_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_TwistedStem_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale0_4_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale1_4_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_ConeScale2_4_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_Cup_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SeedLauncher_Seed_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Moss0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Moss1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Moss2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Moss3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Root0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Root1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Root2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_Root3_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe0_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe0_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe0_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe1_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe1_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe1_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe2_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe2_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe2_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe3_0_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe3_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Leg_RootToe3_2_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Finished glTF 2.0 export in 0.047498464584350586 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_artillery.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w06: 1178 triangles, 53 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_w06.glb +STANDALONE_PASS: w06 +20:13:36 | INFO: Starting glTF 2.0 export +20:13:36 | INFO: Extracting primitive: ArmL_Sickle_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: ArmR_Sickle_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ArchMask_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ArchMask_Eye1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_ArchMask_Eye_1_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_BellSkirt_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_CathedralFrontArch_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_CathedralShell_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_CentralFlow_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_TailL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_TailR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_WispL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Body_WispR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_CentralSpire_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SpireL_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Head_SpireR_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Weapon_Clapper_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Extracting primitive: Weapon_ClapperChain_Mesh +20:13:36 | INFO: Primitives created: 1 +20:13:36 | INFO: Finished glTF 2.0 export in 0.022588491439819336 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_support.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED n08: 1482 triangles, 18 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_n08.glb +STANDALONE_PASS: n08 +20:13:37 | INFO: Starting glTF 2.0 export +20:13:37 | INFO: Extracting primitive: Arm_BasinVine1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Arm_BasinVine_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Heart_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Heart_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Heart_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Heart_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_FrontVine1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_FrontVine_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_SpringArch1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_SpringArch_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf4_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf5_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_CanopyLeaf6_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Moss0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Moss1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Moss2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Moss3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Root0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Root1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Root2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_Root3_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe0_0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe0_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe0_2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe1_0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe1_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe1_2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe2_0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe2_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe2_2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe3_0_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe3_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Leg_RootToe3_2_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_LeafBasin_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_Water_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Finished glTF 2.0 export in 0.04987025260925293 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_mercenary.py:234: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w10: 1290 triangles, 59 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_w10.glb +STANDALONE_PASS: w10 +20:13:37 | INFO: Starting glTF 2.0 export +20:13:37 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmL_Lower_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmL_PauldronCap_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Lower_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_PauldronCap_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Armor_Face_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Armor_Rim_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Belt_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Tabard_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Crest_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Eye1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_HelmetBack_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Visor_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_VisorSlit_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_Boot_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_KneePlate_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_Shin_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_Strap_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_Thigh_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_Boot_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_KneePlate_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_Shin_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_Strap_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_Thigh_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_Haft_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_Head_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_TriangleInset_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_TriangleRim_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_Wedge_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Finished glTF 2.0 export in 0.04204392433166504 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_worker.py:190: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED s04: 10458 triangles, 35 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_s04.glb +STANDALONE_PASS: s04 +20:13:37 | INFO: Starting glTF 2.0 export +20:13:37 | INFO: Extracting primitive: ArmL_Hand_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Hand_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Apron_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_ApronPocket_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_ApronStrap1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_ApronStrap_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Buckle1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Buckle_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Body_Clay_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_ClayFace_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Eye1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_EyeSocket1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_EyeSocket_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_Hood_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Head_HoodEdge_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegL_Foot_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: LegR_Foot_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_CollectedSpark_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_CollectorProng1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_CollectorProng_1_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_CollectorStaff_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_LanternCap0_27_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_LanternCap0_53_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_LanternGlass_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Extracting primitive: Weapon_LanternHandle_Mesh +20:13:37 | INFO: Primitives created: 1 +20:13:37 | INFO: Finished glTF 2.0 export in 0.04176139831542969 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_lane.py:189: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-owe57vwa/scripts/create_lane.py:459: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED worker: 15624 triangles, 28 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/worker.glb +STANDALONE_PASS: worker +20:13:38 | INFO: Starting glTF 2.0 export +20:13:38 | INFO: Extracting primitive: Body_EdgeCap1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap1_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap1_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap_1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap_1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap_1_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeCap_1_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone1_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone1_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone_1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone_1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone_1_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_EdgeStone_1_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneFoundation_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_00_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_01_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_02_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_03_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_04_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LaneSlab_05_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LBasalt_00_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LBasalt_01_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LBasalt_02_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LBrassMarker_00_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LBrassMarker_01_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightGlass1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightGlass1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightGlass_1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightGlass_1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightRecess1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightRecess1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightRecess_1_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LightRecess_1_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LMoss_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_LRetainingLip_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RBasalt_00_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RBasalt_01_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RBasalt_02_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RBrassMarker_00_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RBrassMarker_01_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RMoss_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_RRetainingLip_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Finished glTF 2.0 export in 0.05408167839050293 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_core.py:203: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-owe57vwa/scripts/create_core.py:473: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED map_lane_segment: 10700 triangles, 45 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/map_lane_segment.glb +STANDALONE_PASS: map_lane_segment +20:13:38 | INFO: Starting glTF 2.0 export +20:13:38 | INFO: Extracting primitive: Arm_Cradle_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_Cradle_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_Cradle_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_Cradle_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_CradleClasp_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_CradleClasp_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_CradleClasp_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Arm_CradleClasp_3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_BrassPlinthRim_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_CoreCrystal_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_CorePlinth_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_CradleStep_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_OuterRim_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor4_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor5_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor6_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthArmor7_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold3_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold4_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold5_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold6_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Body_PlinthGold7_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Team_Triangle_0_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Team_Triangle_1_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Extracting primitive: Team_Triangle_2_Mesh +20:13:38 | INFO: Primitives created: 1 +20:13:38 | INFO: Finished glTF 2.0 export in 0.0415959358215332 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_melee.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-owe57vwa/scripts/create_melee.py:525: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED core_team1: 9076 triangles, 32 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/core_team1.glb +STANDALONE_PASS: core_team1 +STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved +20:13:40 | INFO: Starting glTF 2.0 export +20:13:40 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_LavaCore_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell0_0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell0_1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell0_2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell0_3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell1_0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell1_1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell1_2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell1_3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell2_0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell2_1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell2_2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Body_Shell2_3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_BrowL_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_BrowR_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_CheekL_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_CheekR_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_Chin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_EyeL_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_EyeR_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_JawCavity_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_MouthEmber_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +20:13:40 | INFO: Primitives created: 1 +20:13:40 | INFO: Finished glTF 2.0 export in 0.18222355842590332 s +/tmp/saumwacht-standalone-owe57vwa/scripts/create_melee.py:255: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-owe57vwa/scripts/create_melee.py:525: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED g01: 51844 triangles, 131 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_g01.glb +STANDALONE_PASS: g01 +20:13:42 | INFO: Starting glTF 2.0 export +20:13:42 | INFO: Extracting primitive: ArmL_Elbow_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Palm_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_Shoulder_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_UpperBand_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_UpperCore_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_WristBand_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Elbow_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Palm_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_Shoulder_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_UpperBand_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_UpperCore_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_WristBand_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_LavaCore_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell0_0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell0_1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell0_2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell0_3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell1_0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell1_1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell1_2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell1_3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell2_0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell2_1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell2_2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Body_Shell2_3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_BrowL_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_BrowR_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_CheekL_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_CheekR_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_Chin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_EyeL_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_EyeR_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_JawCavity_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothL0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothL1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothL2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothL3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothR0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothR1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothR2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_LowerToothR3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_MouthEmber_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothL0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothL1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothL2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothL3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothR0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothR1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothR2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: Head_UpperToothR3_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_AnklePin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_AnklePivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_AnkleRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_HipPin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_HipPivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_HipRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_InnerShin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_InnerThigh_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_KneeGuard_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_KneePin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_KneePivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_KneeRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_ShinArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_ThighArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_Toe0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_Toe1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_Toe2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_ToeCap0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_ToeCap1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegL_ToeCap2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_AnklePin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_AnklePivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_AnkleRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_HipPin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_HipPivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_HipRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_InnerShin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_InnerThigh_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_KneeGuard_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_KneePin_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_KneePivot_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_KneeRim_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_ShinArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_ThighArmor_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_Toe0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_Toe1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_Toe2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_ToeCap0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_ToeCap1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: LegR_ToeCap2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponL_Claw0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponL_Claw1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponL_Claw2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponR_Claw0_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponR_Claw1_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Extracting primitive: WeaponR_Claw2_Mesh.001 +20:13:42 | INFO: Primitives created: 1 +20:13:42 | INFO: Finished glTF 2.0 export in 0.2286067008972168 s +00:10.182 blend | Read blend: "/tmp/saumwacht-standalone-owe57vwa/blend/n08.blend" + +EXPORTED g01: 51844 triangles, 131 parts -> /tmp/saumwacht-standalone-owe57vwa/exports/unit_g01.glb +STANDALONE_PASS: g01 +KEEP_SCENE_PASS: two generated scenes and original scene retained +Warning: Library file, loading empty scene +NATIVE_BLEND_PASS: isolated N08 scene reopened; 20 objects +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase7-logs/windows-pack.log b/docs/phase7-logs/windows-pack.log new file mode 100644 index 0000000..2afa5ea --- /dev/null +++ b/docs/phase7-logs/windows-pack.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 174 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase7-windows/godot/app_userdata/Saumwacht · Glutpakt/phase7-smoke diff --git a/docs/phase7-package-check.json b/docs/phase7-package-check.json new file mode 100644 index 0000000..f6d5e30 --- /dev/null +++ b/docs/phase7-package-check.json @@ -0,0 +1,19 @@ +{ + "version": "0.7.0", + "packages": [ + { + "platform": "Linux", + "archive_crc": true, + "sha256": "3c041a59f7236066965265ab2ade11b691abc071a21d354b67567c61c1fffcc7", + "executable_sha256_matches": true, + "extracted_executable": "/tmp/saumwacht-phase7-release/Saumwacht-Glutpakt-Linux/Saumwacht.x86_64" + }, + { + "platform": "Windows", + "archive_crc": true, + "sha256": "0e4e8261fe5c8484638097a2ed143dc5c471c4cd8be72984c74f3131bca897db", + "executable_sha256_matches": true, + "extracted_executable": "/tmp/saumwacht-phase7-release/Saumwacht-Glutpakt-Windows/Saumwacht.exe" + } + ] +} diff --git a/docs/phase7-runtime.json b/docs/phase7-runtime.json new file mode 100644 index 0000000..7656c06 --- /dev/null +++ b/docs/phase7-runtime.json @@ -0,0 +1,18 @@ +{ + "audio_events": 54, + "checks": 9, + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "4.7.2-stable (fedora)", + "failures": [], + "frames": 1728, + "max_draw_calls": 1557, + "mean_fps": 143.979926798539, + "mean_frame_ms": 6.94541261574073, + "p95_frame_ms": 8.556, + "renderer": "forward_plus", + "sample_seconds": 12, + "speed": 2, + "units_at_start": 28, + "viewport": "(1600.0, 960.0)", + "wave": 8 +} \ No newline at end of file diff --git a/docs/phase7-verification.json b/docs/phase7-verification.json new file mode 100644 index 0000000..08ceae7 --- /dev/null +++ b/docs/phase7-verification.json @@ -0,0 +1,714 @@ +{ + "capture": false, + "checks": 361, + "failures": [], + "matches": [ + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 177 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 3 + ], + "seconds": 22.3333333333333, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2733 + ], + "damage": [ + 0, + 267 + ], + "gold": [ + 156, + 191 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 3 + ], + "seconds": 32.1499999999995, + "sends": [ + "s02" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 2380 + ], + "damage": [ + 0, + 353 + ], + "gold": [ + 137, + 176 + ], + "leaks": [ + 0, + 11 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 3 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2091 + ], + "damage": [ + 0, + 289 + ], + "gold": [ + 166, + 199 + ], + "leaks": [ + 0, + 2 + ], + "purchases": [ + "Herdhüter", + "Kohlenbeißer" + ], + "roster": [ + 7, + 4 + ], + "seconds": 36.4333333333325, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1716 + ], + "damage": [ + 0, + 375 + ], + "gold": [ + 192, + 171 + ], + "leaks": [ + 0, + 9 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 7, + 6 + ], + "seconds": 36.8999999999992, + "sends": [ + "s02" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1584 + ], + "damage": [ + 0, + 132 + ], + "gold": [ + 193, + 179 + ], + "leaks": [ + 0, + 4 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 8, + 6 + ], + "seconds": 46.5666666666653, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1035 + ], + "damage": [ + 0, + 549 + ], + "gold": [ + 211, + 162 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 9, + 6 + ], + "seconds": 49.9999999999984, + "sends": [ + "s02" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 112 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 157, + 157 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 4 + ], + "seconds": 27.3333333333331, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 142, + 142 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 5 + ], + "seconds": 23.25, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 156, + 156 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 17.6666666666669, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 190, + 190 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 182, + 182 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 6, + 6 + ], + "seconds": 20.7833333333334, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 244, + 244 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Basaltbastion ↑" + ], + "roster": [ + 6, + 6 + ], + "seconds": 24.9666666666665, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "damage": [ + 200, + 0 + ], + "gold": [ + 295, + 139 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "damage": [ + 270, + 0 + ], + "gold": [ + 373, + 112 + ], + "leaks": [ + 10, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "damage": [ + 489, + 0 + ], + "gold": [ + 454, + 150 + ], + "leaks": [ + 11, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 20.0333333333335, + "sends": [], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "damage": [ + 457, + 0 + ], + "gold": [ + 538, + 151 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 20.0666666666668, + "sends": [], + "wave": 4, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "damage": [ + 551, + 0 + ], + "gold": [ + 625, + 161 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 15.3333333333337, + "sends": [], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 304, + 3000 + ], + "damage": [ + 729, + 0 + ], + "gold": [ + 715, + 187 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 18.1166666666669, + "sends": [], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 0, + 3000 + ], + "damage": [ + 304, + 0 + ], + "gold": [ + 715, + 37 + ], + "leaks": [ + 12, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers_ordered": 0 + } + ] + } + ], + "wave_count": 8 +} \ No newline at end of file diff --git a/docs/phase8-QA.md b/docs/phase8-QA.md new file mode 100644 index 0000000..c812203 --- /dev/null +++ b/docs/phase8-QA.md @@ -0,0 +1,48 @@ +# Expedition · Prüfprotokoll der Demo 0.8.0 + +Stand: **16. September 2026**. Godot `4.7.2.stable.fedora.ed1daf0bf`, Release-Template `4.7.2.stable.official.ed1daf0bf`. Grafik: NVIDIA RTX 5060 Ti, Linux, Vulkan Forward+; zusätzlich OpenGL Compatibility. + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | 209 Prüfungen bestanden | +| Unveränderte Kurzpartie, drei reguläre Partien plus Modelle | 373 Prüfungen bestanden | +| Expedition, drei reguläre Partien plus neue Fähigkeiten und Menü | 206 Prüfungen bestanden, headless | +| Aus ZIP entpackte Linux-Demo, Expedition mit Vulkan | 211 Prüfungen bestanden; fünf echte Aufnahmen | +| Entpackte Linux-Demo, Expedition mit OpenGL | 211 Prüfungen bestanden | +| Entpackte Linux-Demo, Kurzpartie | 174 Prüfungen bestanden, headless | +| Windows-PCK mit Linux-Godot | 174 Kurzpartie- und 206 Expeditionsprüfungen bestanden | +| Endkampf bei 2×: Kamera, Fokus und Audio | 9 Prüfungen bestanden | +| GLB-Geometrie einschließlich vier neuer Gegner | 59/59 bestanden, 0 Topologiewarnungen | +| Godot-Import | 59/59 bestanden | +| ZIPs und extrahierte EXE/ELF | CRC, SHA-256 und Programmhashes stimmen | +| Nativer Windows-Lauf | Nicht durchgeführt | + +Die Expedition verwendet dieselben Produktionskommandos wie das Spiel, ohne zusätzliche Matchressourcen. Standard gegen Standard erreicht Welle 20 mit 669 / 669 Kern-HP. Standard gegen Lernmodus gewinnt nach Welle 10 mit 2.038 / 0 HP; leeres Baufeld verliert Welle 7 mit 0 / 3.000. In der Kurzpartie bleiben die Ergebnisse bei Sieg Welle 8 (3.000 / 1.035), Gleichstand Welle 8 (3.000 / 3.000) und Niederlage Welle 7 (0 / 3.000). + +Die neuen Fähigkeitstests erzeugen isolierte Kampffiguren mit gezielt gesetzten HP und Zeiten. Sie prüfen Knotenrufer-Heilung mit dem tatsächlichen HP-Wellenfaktor, Lane-Trennung und Abklingzeit; Maskenrichter mit genau drei verlangsamten Zielen und Ablauf nach drei Sekunden; Bruchstampfer und Schlundkrone mit exaktem Schaden nur beim vierten Treffer, begrenzter Zahl zusätzlicher Ziele und Ausschluss des Primärziels. Diese Testfiguren sind von den regulären Partien getrennt und werden anschließend freigegeben. + +Moduswahl über die HUD-Signale, passende Menütexte, Grenzen 8/20/21, finale Arbeitersperre und Neustart von Expedition zu Kurzpartie sind geprüft. Während einer laufenden Partie wird eine Änderung der Länge abgewiesen. Die vorherigen Modellbetrachter-, Kamera-, Audio- und Optionsprüfungen bleiben im Kurzpartie-Pakettest enthalten. + +## Laufzeit + +Welle 20, 88 Kampfinstanzen zu Messbeginn, 2× Tempo, 1600 × 960. Nach zwei Sekunden Aufwärmen wurden zwölf Sekunden gemessen: **144,01 FPS im Mittel**, **6,94 ms mittlere Framezeit**, **12,44 ms 95. Perzentil**, maximal **3.060 Draw Calls**, 121 Audioereignisse. RTX 5060 Ti mit VSync; keine Aussage über Mindesthardware. [Messdaten](phase8-runtime.json). + +## Reproduzieren + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . res://tools/verify_phase5.tscn -- --phase8 +godot --headless --path . -- --expedition-test +godot --path . -- --expedition-test +godot --path . res://tools/verify_phase6_runtime.tscn -- --expedition +python3 tools/verify_phase4_glb.py --json +godot --headless --path . --script res://tools/verify_phase4_models.gd +``` + +Die Release-Tests liefen mit aus ZIPs entpackten Dateien aus `/tmp`, ohne den Projektordner als Spielquelle. Vollständige Startbefehle einschließlich Windows-PCK-Test: [Builds](phase8-builds.md). Die alten Namen der gemeinsamen Import- und Laufzeittestdateien bleiben erhalten. + +[Expeditionsdaten](phase8-verification.json) · [Wellen und Kaufpläne](phase8-balance.md) · [Kurzpartie-Daten](phase8-short-verification.json) · [GLB-Audit](phase8-glb-audit.json) · [Paket-Hashes](phase8-package-check.json) · [Protokolle](phase8-logs/). + +Aufnahmen aus dem exportierten Spiel: [Menü](screenshots/phase8/menu.png), [Welle 9](screenshots/phase8/wave-09.png), [Welle 15](screenshots/phase8/wave-15.png), [Welle 20](screenshots/phase8/wave-20.png), [Ergebnis](screenshots/phase8/result.png). + +Die Modelle sind stilisierte 3D-Umsetzungen mit starren Gelenken. Menschliche Spieltests und ein nativer Windows-Test stehen aus. Historische Prüfung: [Grafikupdate 0.7.0](phase7-QA.md). diff --git a/docs/phase8-balance.md b/docs/phase8-balance.md new file mode 100644 index 0000000..3ea2d18 --- /dev/null +++ b/docs/phase8-balance.md @@ -0,0 +1,92 @@ +# Glutpakt · Expedition mit 20 Wellen + +Wellen aus den Produktionsdefinitionen; Partien aus `--expedition-test`. Alle Käufe und Sends verwenden reguläre Ressourcen: 220 Gold, ein Arbeiter, 20 Einkommen und 3.000 Kern-HP pro Team. Es werden keine Matchressourcen ergänzt. + +## Progression + +Die Kompositionen entsprechen dem Dossier. Die dortigen Ausgangsfaktoren wurden für die spielbare Wirtschaft reduziert. Für x = Welle − 1 gilt in der Expedition: HP = 1 + 0,10x + 0,004x²; Schaden = 1 + 0,06x + 0,002x²; Prämien = 1 + 0,04x. Die Kurzpartie behält ihre bisherigen Werte (HP 0,14/0,010; Schaden 0,08/0,004). + +Die erste Übertragung mit den Kurzpartie-Faktoren führte im Standard-Spiegeltest bereits in Welle 12 zu zwei zerstörten Kernen. Die neue Kurve erreicht Welle 20 mit 669 / 669 Kern-HP. Hohe Verluste sind besonders in Welle 9 und im Finale möglich; Formationen und Zielwahl beeinflussen das Ergebnis. + +| Welle | Titel | Gegner | Anzahl | HP-Faktor | Schaden | Grundgold | +| ---: | --- | --- | ---: | ---: | ---: | ---: | +| 1 | Erste Risse | 8 × E01 | 8 | 1.000 | 1.000 | 55 | +| 2 | Splitterstrom | 10 × E01 | 10 | 1.104 | 1.062 | 58 | +| 3 | Harte Schalen | 6 × E01, 4 × E02 | 10 | 1.216 | 1.128 | 61 | +| 4 | Fäden im Rücken | 8 × E01, 4 × E04 | 12 | 1.336 | 1.198 | 64 | +| 5 | Der Bruchhirsch | 1 × E07, 6 × E01 | 7 | 1.464 | 1.272 | 67 | +| 6 | Gepanzerter Vorstoß | 6 × E02, 6 × E01 | 12 | 1.600 | 1.350 | 70 | +| 7 | Stimmen aus dem Nebel | 8 × E03, 4 × E01 | 12 | 1.744 | 1.432 | 73 | +| 8 | Gedeckter Vormarsch | 6 × E02, 6 × E04, 4 × E01 | 16 | 1.896 | 1.518 | 76 | +| 9 | Die Knotenrufer | 4 × E05, 6 × E02, 4 × E06 | 14 | 2.056 | 1.608 | 79 | +| 10 | Der Riegelkoloss | 1 × E08, 8 × E03, 4 × E04 | 13 | 2.224 | 1.702 | 82 | +| 11 | Splitterflut | 16 × E01, 6 × E04 | 22 | 2.400 | 1.800 | 85 | +| 12 | Heilende Front | 8 × E02, 4 × E05, 4 × E06 | 16 | 2.584 | 1.902 | 88 | +| 13 | Nebel und Fäden | 12 × E03, 6 × E04 | 18 | 2.776 | 2.008 | 91 | +| 14 | Bruchlinie | 6 × E05, 6 × E02, 6 × E01 | 18 | 2.976 | 2.118 | 94 | +| 15 | Der Maskenrichter | 1 × E09, 6 × E03, 4 × E06 | 11 | 3.184 | 2.232 | 97 | +| 16 | Der große Schwarm | 18 × E01, 6 × E04, 4 × E03 | 28 | 3.400 | 2.350 | 100 | +| 17 | Stampfende Reihen | 8 × E05, 6 × E02, 4 × E06 | 18 | 3.624 | 2.472 | 103 | +| 18 | Rissgesang | 10 × E03, 8 × E04, 4 × E06 | 22 | 3.856 | 2.598 | 106 | +| 19 | Vor dem Schlund | 6 × E05, 8 × E02, 8 × E01, 4 × E04 | 26 | 4.096 | 2.728 | 109 | +| 20 | Die Schlundkrone | 1 × E10, 6 × E05, 6 × E03, 4 × E06 | 17 | 4.344 | 2.862 | 112 | + +## Standard gegen Standard + +| Welle | Kampf s | Kern-HP | Lecks | Wächter | Gold nach Bau | Arbeiter / bestellt | Sends | +| ---: | ---: | --- | --- | ---: | ---: | --- | --- | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 3 | 40 | 1 / 0 | | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 4 | 4 | 1 / 1 | | +| 3 | 24.4 | 3000 / 3000 | 0 / 0 | 4 | 22 | 2 / 0 | s01, s01 | +| 4 | 19.1 | 3000 / 3000 | 0 / 0 | 5 | 2 | 2 / 1 | s01 | +| 5 | 16.3 | 3000 / 3000 | 0 / 0 | 5 | 2 | 3 / 0 | s01 | +| 6 | 19.3 | 3000 / 3000 | 0 / 0 | 5 | 16 | 3 / 0 | s01, s01 | +| 7 | 19.7 | 3000 / 3000 | 0 / 0 | 6 | 15 | 3 / 1 | s01 | +| 8 | 34.5 | 2811 / 2811 | 5 / 5 | 7 | 17 | 4 / 1 | s01, s01 | +| 9 | 43.2 | 2245 / 2245 | 8 / 8 | 8 | 11 | 5 / 0 | s01, s01, s01 | +| 10 | 38.1 | 1790 / 1790 | 9 / 9 | 9 | 2 | 5 / 0 | s01, s01 | +| 11 | 19.2 | 1790 / 1790 | 0 / 0 | 9 | 0 | 5 / 0 | s01, s01, s01 | +| 12 | 46.3 | 1790 / 1790 | 0 / 0 | 10 | 39 | 5 / 1 | s01, s01 | +| 13 | 27.2 | 1790 / 1790 | 0 / 0 | 11 | 9 | 6 / 1 | s01, s01, s01 | +| 14 | 44.1 | 1386 / 1386 | 8 / 8 | 11 | 44 | 7 / 1 | s01, s01, s01, s01 | +| 15 | 26.7 | 1386 / 1386 | 0 / 0 | 13 | 12 | 8 / 0 | s01, s01, s01, s01 | +| 16 | 24.4 | 1386 / 1386 | 0 / 0 | 13 | 11 | 8 / 0 | s01, s01, s01, s01 | +| 17 | 50.4 | 1386 / 1386 | 0 / 0 | 16 | 16 | 8 / 0 | s01, s01, s01, s01 | +| 18 | 26.8 | 1386 / 1386 | 0 / 0 | 19 | 12 | 8 / 0 | s01, s01, s01, s01 | +| 19 | 41.0 | 1386 / 1386 | 0 / 0 | 19 | 38 | 8 / 0 | s01, s01, s01, s01 | +| 20 | 59.0 | 669 / 669 | 8 / 8 | 23 | 19 | 8 / 0 | s01, s01, s01, s01 | + +Ergebnis: Gleichstand. + +## Standard gegen Lernmodus + +| Welle | Kampf s | Kern-HP | Lecks | Wächter | Gold nach Bau | Arbeiter / bestellt | Sends | +| ---: | ---: | --- | --- | ---: | ---: | --- | --- | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 3 | 40 | 1 / 0 | | +| 2 | 21.3 | 3000 / 3000 | 0 / 0 | 4 | 4 | 1 / 1 | | +| 3 | 32.8 | 3000 / 2761 | 0 / 4 | 4 | 22 | 2 / 0 | s02 | +| 4 | 23.6 | 3000 / 2436 | 0 / 10 | 5 | 1 | 2 / 1 | s01 | +| 5 | 50.1 | 3000 / 2317 | 0 / 2 | 7 | 7 | 3 / 0 | s01 | +| 6 | 51.4 | 3000 / 2223 | 0 / 2 | 7 | 26 | 3 / 0 | s02 | +| 7 | 27.6 | 3000 / 2223 | 0 / 0 | 8 | 17 | 3 / 1 | s01 | +| 8 | 37.8 | 3000 / 1726 | 0 / 9 | 9 | 8 | 4 / 1 | s02 | +| 9 | 43.5 | 2038 / 807 | 13 / 12 | 10 | 23 | 5 / 1 | s02, s01 | +| 10 | 35.2 | 2038 / 0 | 0 / 15 | 10 | 37 | 6 / 0 | s01, s01, s01 | + +Ergebnis: Team 0 gewinnt. + +## Leeres Baufeld gegen Standard + +| Welle | Kampf s | Kern-HP | Lecks | Wächter | Gold nach Bau | Arbeiter / bestellt | Sends | +| ---: | ---: | --- | --- | ---: | ---: | --- | --- | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 0 | 220 | 1 / 0 | | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 0 | 295 | 1 / 0 | | +| 3 | 19.3 | 2041 / 3000 | 11 / 0 | 0 | 373 | 1 / 0 | | +| 4 | 18.9 | 1584 / 3000 | 13 / 0 | 0 | 454 | 1 / 0 | | +| 5 | 13.5 | 1033 / 3000 | 8 / 0 | 0 | 538 | 1 / 0 | | +| 6 | 16.4 | 304 / 3000 | 13 / 0 | 0 | 625 | 1 / 0 | | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 0 | 715 | 1 / 0 | | + +Ergebnis: Team 1 gewinnt. + +Die vollständigen bezahlten Formationen mit IDs, Zellen und Investitionen stehen in [phase8-verification.json](phase8-verification.json). KI-Partien sind reproduzierbare Abnahmetests, keine menschliche Erfolgsquote. [Unveränderte Kurzpartie](phase8-short-balance.md). diff --git a/docs/phase8-builds.md b/docs/phase8-builds.md new file mode 100644 index 0000000..930dd38 --- /dev/null +++ b/docs/phase8-builds.md @@ -0,0 +1,48 @@ +# Demo 0.8.0 · Windows und Linux + +## Starten + +Im übergeordneten `dist`-Ordner liegen zwei ZIP-Pakete. Vollständig entpacken. Unter Windows `Saumwacht.exe`, unter Linux `Spielen.sh` oder `Saumwacht.x86_64` starten. Die Programme enthalten ihr PCK; der Projektordner wird nicht benötigt. Bei Vulkan-Problemen startet `Kompatibilitaet.bat` bzw. `Kompatibilitaet.sh` mit OpenGL 3.3. Dieser Modus zeigt dieselbe Geometrie, jedoch ohne SSAO und Glow. + +Die Windows-Demo ist ein nicht signiertes x86-64-GUI-Programm. Sie wird für Windows 10/11 mit Vulkan-fähiger Grafik bereitgestellt. Ein echter Windows-Test steht aus. Die Linux-Demo wurde mit NVIDIA RTX 5060 Ti unter Fedora geprüft; daraus folgt keine Leistungszusage für andere Hardware. + +Im Hauptmenü stehen **Expedition · 20 Wellen · 4 Bosse** und **Kurzpartie · 8 Wellen · 2 Bosse** zur Wahl. Jede Partie startet mit denselben Ressourcen. Die Skalierung der längeren Expedition ist gesondert abgestimmt. + +## Erstellen + +Verwendet werden die offiziellen Release-Templates von [Godot 4.7.2](https://godotengine.org/download/archive/4.7.2-stable/). Die installierte Fedora-Engine und die offiziellen Templates melden denselben Commit `ed1daf0bf`. Godots [Exportdokumentation](https://docs.godotengine.org/en/4.7/tutorials/export/exporting_projects.html) beschreibt das zugrunde liegende Verfahren. + +Die zwei benötigten Dateien aus dem offiziellen TPZ-Archiv liegen unter `assets-source/phase6/export-templates`: + +- `linux_release.x86_64` +- `windows_release_x86_64.exe` +- `version.txt`: `4.7.2.stable` + +Der Quellordner wird durch `.gdignore` nicht in das Spiel aufgenommen. Falls die Templates fehlen, das Standard-Archiv von der oben verlinkten offiziellen Downloadseite beziehen, als ZIP öffnen und nur diese Dateien in den genannten Ordner kopieren. + +```bash +python3 tools/build_demo.py +``` + +`export_presets.cfg` definiert Linux und Windows. Beide nutzen eingebettetes PCK und x86-64. Dokumentation, Entwicklungswerkzeuge, Tests und nicht verwendete UI-/Kartenillustrationen sind ausgeschlossen. Die dynamisch geladenen Assetmanifeste sind ausdrücklich enthalten. Die noch nicht spielbaren Fraktionsmodelle bleiben im Assetkatalog enthalten; die Spielauswahl ist weiterhin Glutpakt. + +Der Build-Schritt schreibt EXE/ELF, ZIPs, Anleitungen, `build-manifest.json`, `SHA256SUMS.txt` und Exportprotokolle in `../dist`. Er benötigt die vorhandenen Lizenzquellen unter `assets-source/phase6/licenses`. + +## Paketprüfung + +```bash +# Außerhalb des Projektordners ausführen: +/path/to/dist/linux/Saumwacht.x86_64 --headless -- --smoke-test +/path/to/dist/linux/Saumwacht.x86_64 -- --smoke-test +/path/to/dist/linux/Saumwacht.x86_64 -- --expedition-test + +# Prüft Windows-Spieldaten mit der Linux-Engine, nicht den Windows-Prozess: +godot --headless --main-pack /path/to/dist/windows/Saumwacht.exe -- --smoke-test +godot --headless --main-pack /path/to/dist/windows/Saumwacht.exe -- --expedition-test +``` + +Der explizite Prüfmodus testet den neuen Modellbetrachter mit Pause/Fokus/Modellwechsel, hohe Dreieckszahlen, Gelenkgeometrie, unabhängige Instanzen, gebündelte Audio-/Bildassets, Optionspause, Fokus, Kamera, Einstellungsdateien und eine komplette bezahlte Acht-Wellen-Partie. Graphisch speichert er acht unveränderte Viewport-Aufnahmen unter `user://phase8-smoke`, einschließlich zweier Modell-Nahansichten. Ohne `--smoke-test` läuft das normale Spiel. + +Einstellungen liegen in `user://preferences.cfg`: unter Windows normalerweise `%APPDATA%/Godot/app_userdata/Saumwacht · Glutpakt`, unter Linux `~/.local/share/godot/app_userdata/Saumwacht · Glutpakt`. Der Test verwendet für seinen Einstellungs-Rundlauf eine eigene temporäre Datei und stellt die vorherigen Einstellungen wieder her. + +`--expedition-test` prüft zusätzlich alle 20 Wellen, die vier neuen Fähigkeiten/Modelle, Menüauswahl und Moduswechsel beim Neustart. Es schreibt `user://phase8-verification.json` und mit Grafikausgabe fünf Aufnahmen nach `user://phase8-captures`. diff --git a/docs/phase8-glb-audit.json b/docs/phase8-glb-audit.json new file mode 100644 index 0000000..70c881f --- /dev/null +++ b/docs/phase8-glb-audit.json @@ -0,0 +1,4921 @@ +{ + "asset_count": 59, + "errors": [], + "assets": [ + { + "id": "g01", + "file": "unit_g01.glb", + "errors": [], + "warnings": [], + "triangles": 51844, + "mesh_parts": 131, + "primitives": 131, + "vertices": 40435, + "closed_meshes": 131, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g02", + "file": "unit_g02.glb", + "errors": [], + "warnings": [], + "triangles": 52056, + "mesh_parts": 133, + "primitives": 133, + "vertices": 40509, + "closed_meshes": 133, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g03", + "file": "unit_g03.glb", + "errors": [], + "warnings": [], + "triangles": 42352, + "mesh_parts": 119, + "primitives": 119, + "vertices": 31773, + "closed_meshes": 119, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g04", + "file": "unit_g04.glb", + "errors": [], + "warnings": [], + "triangles": 61340, + "mesh_parts": 220, + "primitives": 220, + "vertices": 45815, + "closed_meshes": 220, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g05", + "file": "unit_g05.glb", + "errors": [], + "warnings": [], + "triangles": 38388, + "mesh_parts": 118, + "primitives": 118, + "vertices": 29292, + "closed_meshes": 118, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderFin", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderFin", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ChestStoneL", + "Body_ChestStoneR", + "Body_CuirassL", + "Body_CuirassR", + "Body_EmberHeart", + "Body_Spine", + "Head_Crest", + "Head_Helmet", + "Head_Neck", + "Head_Visor", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar10", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceEmber", + "Weapon_LanceShaft", + "Weapon_SpearEdge1", + "Weapon_SpearEdge_1", + "Weapon_SpearHead" + ] + }, + { + "id": "g06", + "file": "unit_g06.glb", + "errors": [], + "warnings": [], + "triangles": 26884, + "mesh_parts": 85, + "primitives": 85, + "vertices": 18642, + "closed_meshes": 85, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrankInsetL", + "Body_CrankInsetR", + "Body_CrankL", + "Body_CrankR", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Body_Gearbox", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoltHead", + "Weapon_CentralBolt", + "Weapon_DrawCableL", + "Weapon_DrawCableR", + "Weapon_GlassLimbL", + "Weapon_GlassLimbR", + "Weapon_LimbClampL", + "Weapon_LimbClampR", + "Weapon_LimbEdgeL", + "Weapon_LimbEdgeR", + "Weapon_RailL", + "Weapon_RailR", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5", + "Weapon_RailTrimL", + "Weapon_RailTrimR", + "Weapon_RearHousing", + "Weapon_RearTrim" + ] + }, + { + "id": "g07", + "file": "unit_g07.glb", + "errors": [], + "warnings": [], + "triangles": 51284, + "mesh_parts": 128, + "primitives": 128, + "vertices": 41969, + "closed_meshes": 128, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "Weapon_EmberBoulder", + "Weapon_LavaPool" + ] + }, + { + "id": "g08", + "file": "unit_g08.glb", + "errors": [], + "warnings": [], + "triangles": 46922, + "mesh_parts": 123, + "primitives": 123, + "vertices": 37253, + "closed_meshes": 123, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "Weapon_LavaPool" + ] + }, + { + "id": "g09", + "file": "unit_g09.glb", + "errors": [], + "warnings": [], + "triangles": 54596, + "mesh_parts": 173, + "primitives": 173, + "vertices": 39482, + "closed_meshes": 173, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone10", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_HearthBack", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Body_OvenDark", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Head_Chimney", + "Head_ChimneyCap", + "Head_ChimneyRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "g10", + "file": "unit_g10.glb", + "errors": [], + "warnings": [], + "triangles": 66734, + "mesh_parts": 223, + "primitives": 223, + "vertices": 47050, + "closed_meshes": 223, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_HearthBack", + "Body_MantleL", + "Body_MantleR", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_OvenDark", + "Body_SolarStream", + "Body_SunFrame", + "Body_SunHeart", + "Body_SunSocket", + "Body_TabardL", + "Body_TabardR", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "m01", + "file": "unit_m01.glb", + "errors": [], + "warnings": [], + "triangles": 1284, + "mesh_parts": 42, + "primitives": 42, + "vertices": 2424, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Upper", + "Body_Belt", + "Body_Chimney", + "Body_ChimneyLip", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_PressureGauge", + "Body_RoundKettle", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m02", + "file": "unit_m02.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2552, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Pauldron", + "ArmL_Shield_Face", + "ArmL_Shield_Rim", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Pauldron", + "ArmR_Shield_Face", + "ArmR_Shield_Rim", + "ArmR_Upper", + "Body_CeramicChest_Face", + "Body_CeramicChest_Rim", + "Body_HeavyChest", + "Body_PressureTankL", + "Body_PressureTankR", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemL", + "Body_ValveStemR", + "Body_ValveWheelL", + "Body_ValveWheelR", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m03", + "file": "unit_m03.glb", + "errors": [], + "warnings": [], + "triangles": 932, + "mesh_parts": 43, + "primitives": 43, + "vertices": 1776, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ] + }, + { + "id": "m04", + "file": "unit_m04.glb", + "errors": [], + "warnings": [], + "triangles": 1398, + "mesh_parts": 60, + "primitives": 60, + "vertices": 2600, + "closed_meshes": 60, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "ArmL1_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "ArmL2_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "ArmR1_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "ArmR2_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL1_Blade0", + "WeaponL2_Blade0", + "WeaponR0_Blade0", + "WeaponR1_Blade0", + "WeaponR2_Blade0" + ] + }, + { + "id": "m05", + "file": "unit_m05.glb", + "errors": [], + "warnings": [], + "triangles": 1148, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2192, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Head_Scope", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m06", + "file": "unit_m06.glb", + "errors": [], + "warnings": [], + "triangles": 1432, + "mesh_parts": 66, + "primitives": 66, + "vertices": 2730, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m07", + "file": "unit_m07.glb", + "errors": [], + "warnings": [], + "triangles": 740, + "mesh_parts": 27, + "primitives": 27, + "vertices": 1403, + "closed_meshes": 27, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_ResonatorHousing0", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston" + ] + }, + { + "id": "m08", + "file": "unit_m08.glb", + "errors": [], + "warnings": [], + "triangles": 1316, + "mesh_parts": 50, + "primitives": 50, + "vertices": 2464, + "closed_meshes": 50, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_HousingLatch1_1", + "Body_HousingLatch1__1", + "Body_ResonatorHousing0", + "Body_ResonatorHousing1", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_DiscPiston0", + "Weapon_DiscPiston1", + "Weapon_ImpactDisc0", + "Weapon_ImpactDisc1" + ] + }, + { + "id": "m09", + "file": "unit_m09.glb", + "errors": [], + "warnings": [], + "triangles": 1160, + "mesh_parts": 51, + "primitives": 51, + "vertices": 2146, + "closed_meshes": 51, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_PendulumBob", + "Body_PendulumStem", + "Body_Waist", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "m10", + "file": "unit_m10.glb", + "errors": [], + "warnings": [], + "triangles": 946, + "mesh_parts": 49, + "primitives": 49, + "vertices": 1828, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Upper", + "Body_Coat", + "Body_CoatGoldL", + "Body_CoatGoldR", + "Body_CreamStoleL", + "Body_CreamStoleR", + "Body_PendulumBob", + "Body_PendulumOpening", + "Body_PendulumStem", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "n01", + "file": "unit_n01.glb", + "errors": [], + "warnings": [], + "triangles": 1132, + "mesh_parts": 16, + "primitives": 16, + "vertices": 3232, + "closed_meshes": 16, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Claw", + "WeaponR_Claw" + ] + }, + { + "id": "n02", + "file": "unit_n02.glb", + "errors": [], + "warnings": [], + "triangles": 1156, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3304, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1" + ] + }, + { + "id": "n03", + "file": "unit_n03.glb", + "errors": [], + "warnings": [], + "triangles": 934, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2688, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Sickle", + "WeaponR_Sickle" + ] + }, + { + "id": "n04", + "file": "unit_n04.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3932, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CrescentCrown", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_ShearLoopLower", + "Weapon_ShearLoopUpper", + "Weapon_ShearLower", + "Weapon_ShearPivot", + "Weapon_ShearUpper" + ] + }, + { + "id": "n05", + "file": "unit_n05.glb", + "errors": [], + "warnings": [], + "triangles": 1118, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2986, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip" + ] + }, + { + "id": "n06", + "file": "unit_n06.glb", + "errors": [], + "warnings": [], + "triangles": 1498, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3844, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_HornArchL", + "Weapon_HornArchR", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ] + }, + { + "id": "n07", + "file": "unit_n07.glb", + "errors": [], + "warnings": [], + "triangles": 1274, + "mesh_parts": 15, + "primitives": 15, + "vertices": 3354, + "closed_meshes": 15, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_BellRim", + "Weapon_Clapper", + "Weapon_ClapperStem", + "Weapon_HangingBell" + ] + }, + { + "id": "n08", + "file": "unit_n08.glb", + "errors": [], + "warnings": [], + "triangles": 1482, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3958, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Sickle", + "ArmR_Sickle", + "Body_ArchMask", + "Body_ArchMask_Eye1", + "Body_ArchMask_Eye_1", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Body_CathedralShell", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CentralSpire", + "Head_SpireL", + "Head_SpireR", + "Weapon_Clapper", + "Weapon_ClapperChain" + ] + }, + { + "id": "n09", + "file": "unit_n09.glb", + "errors": [], + "warnings": [], + "triangles": 1314, + "mesh_parts": 24, + "primitives": 24, + "vertices": 3740, + "closed_meshes": 24, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "n10", + "file": "unit_n10.glb", + "errors": [], + "warnings": [], + "triangles": 1734, + "mesh_parts": 40, + "primitives": 40, + "vertices": 4872, + "closed_meshes": 40, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirHorn1_1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn2_1", + "Head_ChoirHorn2__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Mouth", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp0", + "Head_ChoirWisp1", + "Head_ChoirWisp2", + "Head_CurledHood", + "Head_GreatHorn1", + "Head_GreatHorn_1", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "w01", + "file": "unit_w01.glb", + "errors": [], + "warnings": [], + "triangles": 576, + "mesh_parts": 36, + "primitives": 36, + "vertices": 1460, + "closed_meshes": 36, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BarkPlate0", + "Body_BarkPlate1", + "Body_BarkPlate2", + "Body_BarkPlate3", + "Body_BarkPlate4", + "Body_BarkPlate5", + "Body_BarkPlate6", + "Body_Flower_Heart", + "Body_Flower_Petal0", + "Body_Flower_Petal1", + "Body_Flower_Petal2", + "Body_Flower_Petal3", + "Body_Flower_Petal4", + "Body_MossCore", + "Body_Thorn0", + "Body_Thorn1", + "Body_Thorn2", + "Body_Thorn3", + "Body_Thorn4", + "Body_Thorn5", + "Body_Thorn6", + "Head_Eye1", + "Head_EyeSlit", + "Head_Eye_1", + "Head_Leaf1", + "Head_Leaf_1", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Root0", + "Leg_Root1", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2" + ] + }, + { + "id": "w02", + "file": "unit_w02.glb", + "errors": [], + "warnings": [], + "triangles": 1140, + "mesh_parts": 55, + "primitives": 55, + "vertices": 3172, + "closed_meshes": 55, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BraidedVine0", + "Body_BraidedVine1", + "Body_BraidedVine2", + "Body_VineMass", + "Head_GreenLipL", + "Head_GreenLipR", + "Head_JawFlowerL_Heart", + "Head_JawFlowerL_Petal0", + "Head_JawFlowerL_Petal1", + "Head_JawFlowerL_Petal2", + "Head_JawFlowerL_Petal3", + "Head_JawFlowerL_Petal4", + "Head_JawFlowerR_Heart", + "Head_JawFlowerR_Petal0", + "Head_JawFlowerR_Petal1", + "Head_JawFlowerR_Petal2", + "Head_JawFlowerR_Petal3", + "Head_JawFlowerR_Petal4", + "Head_JawLeafL", + "Head_JawLeafR", + "Head_LowerFangL0", + "Head_LowerFangL1", + "Head_LowerFangL2", + "Head_LowerFangR0", + "Head_LowerFangR1", + "Head_LowerFangR2", + "Head_LowerJaw", + "Head_MouthShadow", + "Head_UpperFangL0", + "Head_UpperFangL1", + "Head_UpperFangL2", + "Head_UpperFangR0", + "Head_UpperFangR1", + "Head_UpperFangR2", + "Head_UpperJaw", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w03", + "file": "unit_w03.glb", + "errors": [], + "warnings": [], + "triangles": 848, + "mesh_parts": 49, + "primitives": 49, + "vertices": 2204, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CorkTile0_0", + "Body_CorkTile0_1", + "Body_CorkTile0_2", + "Body_CorkTile0_3", + "Body_CorkTile0_4", + "Body_CorkTile1_0", + "Body_CorkTile1_1", + "Body_CorkTile1_2", + "Body_CorkTile1_3", + "Body_CorkTile1_4", + "Body_CorkTile2_0", + "Body_CorkTile2_1", + "Body_CorkTile2_2", + "Body_CorkTile2_3", + "Body_CorkTile2_4", + "Body_CrownLeaf", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_MossDome", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w04", + "file": "unit_w04.glb", + "errors": [], + "warnings": [], + "triangles": 1760, + "mesh_parts": 55, + "primitives": 55, + "vertices": 3852, + "closed_meshes": 55, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_LogShield0_Bark", + "Body_LogShield0_Cut", + "Body_LogShield0_GrowthRing0", + "Body_LogShield0_GrowthRing1", + "Body_LogShield1_Bark", + "Body_LogShield1_Cut", + "Body_LogShield1_GrowthRing0", + "Body_LogShield1_GrowthRing1", + "Body_LogShield2_Bark", + "Body_LogShield2_Cut", + "Body_LogShield2_GrowthRing0", + "Body_LogShield2_GrowthRing1", + "Body_LogShield3_Bark", + "Body_LogShield3_Cut", + "Body_LogShield3_GrowthRing0", + "Body_LogShield3_GrowthRing1", + "Body_LogShield4_Bark", + "Body_LogShield4_Cut", + "Body_LogShield4_GrowthRing0", + "Body_LogShield4_GrowthRing1", + "Body_MossDome", + "Head_Sprout1", + "Head_Sprout_1", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w05", + "file": "unit_w05.glb", + "errors": [], + "warnings": [], + "triangles": 878, + "mesh_parts": 35, + "primitives": 35, + "vertices": 2372, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BroadLeaf1", + "Body_BroadLeaf_1", + "Body_ClimbingVine", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_TwistedStem", + "Head_SeedLauncher_Cup", + "Head_SeedLauncher_LipLeaf1", + "Head_SeedLauncher_LipLeaf_1", + "Head_SeedLauncher_Seed", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2" + ] + }, + { + "id": "w06", + "file": "unit_w06.glb", + "errors": [], + "warnings": [], + "triangles": 1178, + "mesh_parts": 53, + "primitives": 53, + "vertices": 3072, + "closed_meshes": 53, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BroadLeaf1", + "Body_BroadLeaf_1", + "Body_ClimbingVine", + "Body_Flower1_Heart", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower_1_Heart", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_TwistedStem", + "Head_SeedLauncher_ConeScale0_0", + "Head_SeedLauncher_ConeScale0_1", + "Head_SeedLauncher_ConeScale0_2", + "Head_SeedLauncher_ConeScale0_3", + "Head_SeedLauncher_ConeScale0_4", + "Head_SeedLauncher_ConeScale1_0", + "Head_SeedLauncher_ConeScale1_1", + "Head_SeedLauncher_ConeScale1_2", + "Head_SeedLauncher_ConeScale1_3", + "Head_SeedLauncher_ConeScale1_4", + "Head_SeedLauncher_ConeScale2_0", + "Head_SeedLauncher_ConeScale2_1", + "Head_SeedLauncher_ConeScale2_2", + "Head_SeedLauncher_ConeScale2_3", + "Head_SeedLauncher_ConeScale2_4", + "Head_SeedLauncher_Cup", + "Head_SeedLauncher_Seed", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w07", + "file": "unit_w07.glb", + "errors": [], + "warnings": [], + "triangles": 1056, + "mesh_parts": 43, + "primitives": 43, + "vertices": 2568, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_ChaliceTrunk", + "Body_SideFungus1_MossFringe0", + "Body_SideFungus1_MossFringe1", + "Body_SideFungus1_MossFringe2", + "Body_SideFungus1_MossRim", + "Body_SideFungus1_PinkCup", + "Body_SideFungus_1_MossFringe0", + "Body_SideFungus_1_MossFringe1", + "Body_SideFungus_1_MossFringe2", + "Body_SideFungus_1_MossRim", + "Body_SideFungus_1_PinkCup", + "Head_SporeChalice_MossFringe0", + "Head_SporeChalice_MossFringe1", + "Head_SporeChalice_MossFringe2", + "Head_SporeChalice_MossFringe3", + "Head_SporeChalice_MossFringe4", + "Head_SporeChalice_MossFringe5", + "Head_SporeChalice_MossRim", + "Head_SporeChalice_PinkCup", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2", + "Weapon_Spore0", + "Weapon_Spore1", + "Weapon_Spore2", + "Weapon_Spore3" + ] + }, + { + "id": "w08", + "file": "unit_w08.glb", + "errors": [], + "warnings": [], + "triangles": 1634, + "mesh_parts": 62, + "primitives": 62, + "vertices": 3736, + "closed_meshes": 62, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_FungalTrunk0", + "Body_FungalTrunk1", + "Body_FungalTrunk2", + "Body_SmallFungus0_MossFringe0", + "Body_SmallFungus0_MossFringe1", + "Body_SmallFungus0_MossFringe2", + "Body_SmallFungus0_MossRim", + "Body_SmallFungus0_PinkCup", + "Body_SmallFungus1_MossFringe0", + "Body_SmallFungus1_MossFringe1", + "Body_SmallFungus1_MossFringe2", + "Body_SmallFungus1_MossRim", + "Body_SmallFungus1_PinkCup", + "Body_SmallFungus2_MossFringe0", + "Body_SmallFungus2_MossFringe1", + "Body_SmallFungus2_MossFringe2", + "Body_SmallFungus2_MossRim", + "Body_SmallFungus2_PinkCup", + "Head_FungalTier0_MossFringe0", + "Head_FungalTier0_MossFringe1", + "Head_FungalTier0_MossFringe2", + "Head_FungalTier0_MossFringe3", + "Head_FungalTier0_MossFringe4", + "Head_FungalTier0_MossFringe5", + "Head_FungalTier0_MossRim", + "Head_FungalTier0_PinkCup", + "Head_FungalTier1_MossFringe0", + "Head_FungalTier1_MossFringe1", + "Head_FungalTier1_MossFringe2", + "Head_FungalTier1_MossFringe3", + "Head_FungalTier1_MossFringe4", + "Head_FungalTier1_MossFringe5", + "Head_FungalTier1_MossRim", + "Head_FungalTier1_PinkCup", + "Head_FungalTier2_MossFringe0", + "Head_FungalTier2_MossFringe1", + "Head_FungalTier2_MossFringe2", + "Head_FungalTier2_MossFringe3", + "Head_FungalTier2_MossFringe4", + "Head_FungalTier2_MossFringe5", + "Head_FungalTier2_MossRim", + "Head_FungalTier2_PinkCup", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2" + ] + }, + { + "id": "w09", + "file": "unit_w09.glb", + "errors": [], + "warnings": [], + "triangles": 812, + "mesh_parts": 31, + "primitives": 31, + "vertices": 2138, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Arm_BasinVine1", + "Arm_BasinVine_1", + "Body_LivingTrunk", + "Body_WindingVine", + "Head_Flower_Heart", + "Head_Flower_Petal0", + "Head_Flower_Petal1", + "Head_Flower_Petal2", + "Head_Flower_Petal3", + "Head_Flower_Petal4", + "Head_LeafCrown0", + "Head_LeafCrown1", + "Head_LeafCrown2", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Weapon_DewOrb", + "Weapon_LeafBasin", + "Weapon_Water" + ] + }, + { + "id": "w10", + "file": "unit_w10.glb", + "errors": [], + "warnings": [], + "triangles": 1290, + "mesh_parts": 59, + "primitives": 59, + "vertices": 3458, + "closed_meshes": 59, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Arm_BasinVine1", + "Arm_BasinVine_1", + "Body_Blossom0_Heart", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom1_Heart", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom2_Heart", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom3_Heart", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_FrontVine1", + "Body_FrontVine_1", + "Body_SpringArch1", + "Body_SpringArch_1", + "Head_CanopyLeaf0", + "Head_CanopyLeaf1", + "Head_CanopyLeaf2", + "Head_CanopyLeaf3", + "Head_CanopyLeaf4", + "Head_CanopyLeaf5", + "Head_CanopyLeaf6", + "Leg_Moss0", + "Leg_Moss1", + "Leg_Moss2", + "Leg_Moss3", + "Leg_Root0", + "Leg_Root1", + "Leg_Root2", + "Leg_Root3", + "Leg_RootToe0_0", + "Leg_RootToe0_1", + "Leg_RootToe0_2", + "Leg_RootToe1_0", + "Leg_RootToe1_1", + "Leg_RootToe1_2", + "Leg_RootToe2_0", + "Leg_RootToe2_1", + "Leg_RootToe2_2", + "Leg_RootToe3_0", + "Leg_RootToe3_1", + "Leg_RootToe3_2", + "Weapon_LeafBasin", + "Weapon_Water" + ] + }, + { + "id": "s01", + "file": "unit_s01.glb", + "errors": [], + "warnings": [], + "triangles": 10340, + "mesh_parts": 34, + "primitives": 34, + "vertices": 8466, + "closed_meshes": 34, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_DiagonalBelt", + "Body_LeatherCuirass", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Scarf", + "Body_SplitCoat1", + "Body_SplitCoat_1", + "Body_TornScarf1", + "Body_TornScarf_1", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_Bolt", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_CrossbowStock", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "s02", + "file": "unit_s02.glb", + "errors": [], + "warnings": [], + "triangles": 12040, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9256, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Corner10_4", + "Weapon_Corner11_16", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_ShieldBoss", + "Weapon_ShieldSpine", + "Weapon_TowerShield_Face", + "Weapon_TowerShield_Rim" + ] + }, + { + "id": "s03", + "file": "unit_s03.glb", + "errors": [], + "warnings": [], + "triangles": 7832, + "mesh_parts": 19, + "primitives": 19, + "vertices": 6089, + "closed_meshes": 19, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_CreamStole1", + "Body_CreamStole_1", + "Body_LongRobe", + "Body_RaggedCloak1", + "Body_RaggedCloak_1", + "Body_Scarf", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "Weapon_Trumpet" + ] + }, + { + "id": "s04", + "file": "unit_s04.glb", + "errors": [], + "warnings": [], + "triangles": 10458, + "mesh_parts": 35, + "primitives": 35, + "vertices": 8062, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Haft", + "Weapon_Head", + "Weapon_TriangleInset", + "Weapon_TriangleRim", + "Weapon_Wedge" + ] + }, + { + "id": "s05", + "file": "unit_s05.glb", + "errors": [], + "warnings": [], + "triangles": 10440, + "mesh_parts": 31, + "primitives": 31, + "vertices": 8279, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_HipRag1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_HollowRib_1", + "Body_RiftEdge1", + "Body_RiftEdge_1", + "Body_TornCloth1", + "Body_TornCloth_1", + "Head_Antler1", + "Head_Antler_1", + "Head_FacelessHelm", + "Head_InnerHorn1", + "Head_InnerHorn_1", + "Head_MintCrack", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_RiftLight", + "Weapon_RiftOrb" + ] + }, + { + "id": "worker", + "file": "worker.glb", + "errors": [], + "warnings": [], + "triangles": 15624, + "mesh_parts": 28, + "primitives": 28, + "vertices": 13116, + "closed_meshes": 28, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Hand", + "ArmL_Shoulder", + "ArmR_Hand", + "ArmR_Shoulder", + "Body_Apron", + "Body_ApronPocket", + "Body_ApronStrap1", + "Body_ApronStrap_1", + "Body_Buckle1", + "Body_Buckle_1", + "Body_Clay", + "Head_ClayFace", + "Head_Eye1", + "Head_EyeSocket1", + "Head_EyeSocket_1", + "Head_Eye_1", + "Head_Hood", + "Head_HoodEdge", + "LegL_Foot", + "LegR_Foot", + "Weapon_CollectedSpark", + "Weapon_CollectorProng1", + "Weapon_CollectorProng_1", + "Weapon_CollectorStaff", + "Weapon_LanternCap0_27", + "Weapon_LanternCap0_53", + "Weapon_LanternGlass", + "Weapon_LanternHandle" + ] + }, + { + "id": "map_lane_segment", + "file": "map_lane_segment.glb", + "errors": [], + "warnings": [], + "triangles": 10700, + "mesh_parts": 45, + "primitives": 45, + "vertices": 8523, + "closed_meshes": 45, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeCap1_0", + "Body_EdgeCap1_1", + "Body_EdgeCap1_2", + "Body_EdgeCap1_3", + "Body_EdgeCap_1_0", + "Body_EdgeCap_1_1", + "Body_EdgeCap_1_2", + "Body_EdgeCap_1_3", + "Body_EdgeStone1_0", + "Body_EdgeStone1_1", + "Body_EdgeStone1_2", + "Body_EdgeStone1_3", + "Body_EdgeStone_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeStone_1_3", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_LRetainingLip", + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LightGlass1_0", + "Body_LightGlass1_1", + "Body_LightGlass_1_0", + "Body_LightGlass_1_1", + "Body_LightRecess1_0", + "Body_LightRecess1_1", + "Body_LightRecess_1_0", + "Body_LightRecess_1_1", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Body_RRetainingLip" + ] + }, + { + "id": "core_team0", + "file": "core_team0.glb", + "errors": [], + "warnings": [], + "triangles": 9728, + "mesh_parts": 30, + "primitives": 30, + "vertices": 7438, + "closed_meshes": 30, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_CoreEffect", + "Arm_CradleClasp_0", + "Arm_CradleClasp_1", + "Arm_CradleClasp_2", + "Arm_CradleClasp_3", + "Arm_Cradle_0", + "Arm_Cradle_1", + "Arm_Cradle_2", + "Arm_Cradle_3", + "Body_BrassPlinthRim", + "Body_CoreCrystal", + "Body_CorePlinth", + "Body_CradleStep", + "Body_OuterRim", + "Body_PlinthArmor0", + "Body_PlinthArmor1", + "Body_PlinthArmor2", + "Body_PlinthArmor3", + "Body_PlinthArmor4", + "Body_PlinthArmor5", + "Body_PlinthArmor6", + "Body_PlinthArmor7", + "Body_PlinthGold0", + "Body_PlinthGold1", + "Body_PlinthGold2", + "Body_PlinthGold3", + "Body_PlinthGold4", + "Body_PlinthGold5", + "Body_PlinthGold6", + "Body_PlinthGold7", + "Team_Circle" + ] + }, + { + "id": "core_team1", + "file": "core_team1.glb", + "errors": [], + "warnings": [], + "triangles": 9076, + "mesh_parts": 32, + "primitives": 32, + "vertices": 7093, + "closed_meshes": 32, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_CoreEffect", + "Arm_CradleClasp_0", + "Arm_CradleClasp_1", + "Arm_CradleClasp_2", + "Arm_CradleClasp_3", + "Arm_Cradle_0", + "Arm_Cradle_1", + "Arm_Cradle_2", + "Arm_Cradle_3", + "Body_BrassPlinthRim", + "Body_CoreCrystal", + "Body_CorePlinth", + "Body_CradleStep", + "Body_OuterRim", + "Body_PlinthArmor0", + "Body_PlinthArmor1", + "Body_PlinthArmor2", + "Body_PlinthArmor3", + "Body_PlinthArmor4", + "Body_PlinthArmor5", + "Body_PlinthArmor6", + "Body_PlinthArmor7", + "Body_PlinthGold0", + "Body_PlinthGold1", + "Body_PlinthGold2", + "Body_PlinthGold3", + "Body_PlinthGold4", + "Body_PlinthGold5", + "Body_PlinthGold6", + "Body_PlinthGold7", + "Team_Triangle_0", + "Team_Triangle_1", + "Team_Triangle_2" + ] + }, + { + "id": "e01", + "file": "enemy_e01.glb", + "errors": [], + "warnings": [], + "triangles": 11984, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9859, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e02", + "file": "enemy_e02.glb", + "errors": [], + "warnings": [], + "triangles": 12936, + "mesh_parts": 42, + "primitives": 42, + "vertices": 10343, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Body_Spine0", + "Body_Spine1", + "Body_Spine2", + "Body_Spine3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e03", + "file": "enemy_e03.glb", + "errors": [], + "warnings": [], + "triangles": 22774, + "mesh_parts": 69, + "primitives": 69, + "vertices": 17771, + "closed_meshes": 69, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_RiftHalo", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull" + ] + }, + { + "id": "e04", + "file": "enemy_e04.glb", + "errors": [], + "warnings": [], + "triangles": 36000, + "mesh_parts": 110, + "primitives": 110, + "vertices": 27851, + "closed_meshes": 110, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_Arrow", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "e05", + "file": "enemy_e05.glb", + "errors": [], + "warnings": [], + "triangles": 41846, + "mesh_parts": 125, + "primitives": 125, + "vertices": 32194, + "closed_meshes": 125, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0", + "ArmL_Knuckle1", + "ArmL_Knuckle2", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_StoneHammer", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Cuff", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0", + "ArmR_Knuckle1", + "ArmR_Knuckle2", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_StoneHammer", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_BackSlab0", + "Body_BackSlab1", + "Body_BackSlab2", + "Body_BackSlab3", + "Body_BruteCore", + "Body_Chest0_1", + "Body_Chest0__1", + "Body_Chest1_1", + "Body_Chest1__1", + "Body_Chest2_1", + "Body_Chest2__1", + "Body_RiftCrack", + "Body_ShoulderSpikeL0", + "Body_ShoulderSpikeL1", + "Body_ShoulderSpikeL2", + "Body_ShoulderSpikeR0", + "Body_ShoulderSpikeR1", + "Body_ShoulderSpikeR2", + "Head_Mask_EyeLight1", + "Head_Mask_EyeLight_1", + "Head_Mask_EyeSocket1", + "Head_Mask_EyeSocket_1", + "Head_Mask_MouthSlit0", + "Head_Mask_MouthSlit1", + "Head_Mask_MouthSlit2", + "Head_Mask_Nose", + "Head_Mask_Porcelain", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e06", + "file": "enemy_e06.glb", + "errors": [], + "warnings": [], + "triangles": 29198, + "mesh_parts": 84, + "primitives": 84, + "vertices": 21723, + "closed_meshes": 84, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HealingKnot0", + "Body_HealingKnot1", + "Body_HealingKnot2", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e07", + "file": "enemy_e07.glb", + "errors": [], + "warnings": [], + "triangles": 16144, + "mesh_parts": 49, + "primitives": 49, + "vertices": 13447, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "Body_DeerCore", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_Tail", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_AntlerR", + "Head_EyeL", + "Head_EyeR", + "Head_Muzzle", + "Head_Neck", + "Head_Nose", + "Head_Skull", + "LegL0_ClovenLine", + "LegL0_Hoof", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_ClovenLine", + "LegL1_Hoof", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Upper", + "LegR0_ClovenLine", + "LegR0_Hoof", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_ClovenLine", + "LegR1_Hoof", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Upper" + ] + }, + { + "id": "e08", + "file": "enemy_e08.glb", + "errors": [], + "warnings": [], + "triangles": 61816, + "mesh_parts": 222, + "primitives": 222, + "vertices": 46057, + "closed_meshes": 222, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_RiftHorn1", + "Body_RiftHorn_1", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e09", + "file": "enemy_e09.glb", + "errors": [], + "warnings": [], + "triangles": 38172, + "mesh_parts": 135, + "primitives": 135, + "vertices": 27726, + "closed_meshes": 135, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_Chains1", + "Body_Chains_1", + "Body_CourtMask0_EyeLight1", + "Body_CourtMask0_EyeLight_1", + "Body_CourtMask0_EyeSocket1", + "Body_CourtMask0_EyeSocket_1", + "Body_CourtMask0_MouthSlit0", + "Body_CourtMask0_MouthSlit1", + "Body_CourtMask0_MouthSlit2", + "Body_CourtMask0_Nose", + "Body_CourtMask0_Porcelain", + "Body_CourtMask1_EyeLight1", + "Body_CourtMask1_EyeLight_1", + "Body_CourtMask1_EyeSocket1", + "Body_CourtMask1_EyeSocket_1", + "Body_CourtMask1_MouthSlit0", + "Body_CourtMask1_MouthSlit1", + "Body_CourtMask1_MouthSlit2", + "Body_CourtMask1_Nose", + "Body_CourtMask1_Porcelain", + "Body_CourtMask2_EyeLight1", + "Body_CourtMask2_EyeLight_1", + "Body_CourtMask2_EyeSocket1", + "Body_CourtMask2_EyeSocket_1", + "Body_CourtMask2_MouthSlit0", + "Body_CourtMask2_MouthSlit1", + "Body_CourtMask2_MouthSlit2", + "Body_CourtMask2_Nose", + "Body_CourtMask2_Porcelain", + "Body_CourtMask3_EyeLight1", + "Body_CourtMask3_EyeLight_1", + "Body_CourtMask3_EyeSocket1", + "Body_CourtMask3_EyeSocket_1", + "Body_CourtMask3_MouthSlit0", + "Body_CourtMask3_MouthSlit1", + "Body_CourtMask3_MouthSlit2", + "Body_CourtMask3_Nose", + "Body_CourtMask3_Porcelain", + "Body_CourtMask4_EyeLight1", + "Body_CourtMask4_EyeLight_1", + "Body_CourtMask4_EyeSocket1", + "Body_CourtMask4_EyeSocket_1", + "Body_CourtMask4_MouthSlit0", + "Body_CourtMask4_MouthSlit1", + "Body_CourtMask4_MouthSlit2", + "Body_CourtMask4_Nose", + "Body_CourtMask4_Porcelain", + "Body_CrownSpike0", + "Body_CrownSpike1", + "Body_CrownSpike2", + "Body_CrownSpike3", + "Body_CrownSpike4", + "Body_JudgeGlow", + "Body_JudgeHalo", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e10", + "file": "enemy_e10.glb", + "errors": [], + "warnings": [], + "triangles": 32572, + "mesh_parts": 82, + "primitives": 82, + "vertices": 25004, + "closed_meshes": 82, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrownCore", + "Body_RidgeL0", + "Body_RidgeL1", + "Body_RidgeL2", + "Body_RidgeL3", + "Body_RidgeR0", + "Body_RidgeR1", + "Body_RidgeR2", + "Body_RidgeR3", + "Body_ShellL0", + "Body_ShellL1", + "Body_ShellL2", + "Body_ShellL3", + "Body_ShellR0", + "Body_ShellR1", + "Body_ShellR2", + "Body_ShellR3", + "Body_Tail", + "Head_Brow1", + "Head_Brow_1", + "Head_CrownBand", + "Head_CrownGem0", + "Head_CrownGem1", + "Head_CrownGem2", + "Head_CrownGem3", + "Head_CrownGem4", + "Head_CrownGem5", + "Head_CrownGem6", + "Head_CrownPoint0", + "Head_CrownPoint1", + "Head_CrownPoint2", + "Head_CrownPoint3", + "Head_CrownPoint4", + "Head_CrownPoint5", + "Head_CrownPoint6", + "Head_Eye1", + "Head_Eye_1", + "Head_MawRim", + "Head_MawVoid", + "Head_RiftThroat", + "Head_Tooth0", + "Head_Tooth1", + "Head_Tooth10", + "Head_Tooth11", + "Head_Tooth12", + "Head_Tooth13", + "Head_Tooth2", + "Head_Tooth3", + "Head_Tooth4", + "Head_Tooth5", + "Head_Tooth6", + "Head_Tooth7", + "Head_Tooth8", + "Head_Tooth9", + "LegL0_Claw0", + "LegL0_Claw1", + "LegL0_Claw2", + "LegL0_Inner", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Thigh", + "LegL1_Claw0", + "LegL1_Claw1", + "LegL1_Claw2", + "LegL1_Inner", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Thigh", + "LegR0_Claw0", + "LegR0_Claw1", + "LegR0_Claw2", + "LegR0_Inner", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Thigh", + "LegR1_Claw0", + "LegR1_Claw1", + "LegR1_Claw2", + "LegR1_Inner", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Thigh" + ] + } + ], + "upgrade_pairs": [ + { + "base": "g01", + "upgrade": "g02", + "structurally_distinct": true + }, + { + "base": "g03", + "upgrade": "g04", + "structurally_distinct": true + }, + { + "base": "g05", + "upgrade": "g06", + "structurally_distinct": true + }, + { + "base": "g07", + "upgrade": "g08", + "structurally_distinct": true + }, + { + "base": "g09", + "upgrade": "g10", + "structurally_distinct": true + }, + { + "base": "m01", + "upgrade": "m02", + "structurally_distinct": true + }, + { + "base": "m03", + "upgrade": "m04", + "structurally_distinct": true + }, + { + "base": "m05", + "upgrade": "m06", + "structurally_distinct": true + }, + { + "base": "m07", + "upgrade": "m08", + "structurally_distinct": true + }, + { + "base": "m09", + "upgrade": "m10", + "structurally_distinct": true + }, + { + "base": "n01", + "upgrade": "n02", + "structurally_distinct": true + }, + { + "base": "n03", + "upgrade": "n04", + "structurally_distinct": true + }, + { + "base": "n05", + "upgrade": "n06", + "structurally_distinct": true + }, + { + "base": "n07", + "upgrade": "n08", + "structurally_distinct": true + }, + { + "base": "n09", + "upgrade": "n10", + "structurally_distinct": true + }, + { + "base": "w01", + "upgrade": "w02", + "structurally_distinct": true + }, + { + "base": "w03", + "upgrade": "w04", + "structurally_distinct": true + }, + { + "base": "w05", + "upgrade": "w06", + "structurally_distinct": true + }, + { + "base": "w07", + "upgrade": "w08", + "structurally_distinct": true + }, + { + "base": "w09", + "upgrade": "w10", + "structurally_distinct": true + } + ], + "passed": true, + "warning_count": 0 +} diff --git a/docs/phase8-logs/acceptance.log b/docs/phase8-logs/acceptance.log new file mode 100644 index 0000000..99bacdf --- /dev/null +++ b/docs/phase8-logs/acceptance.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 206 checks; 0 failures; report /tmp/saumwacht-phase8-accept/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/compat.log b/docs/phase8-logs/compat.log new file mode 100644 index 0000000..fcb20d1 --- /dev/null +++ b/docs/phase8-logs/compat.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 211 checks; 0 failures; report /tmp/saumwacht-phase8-compat/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/godot-models.log b/docs/phase8-logs/godot-models.log new file mode 100644 index 0000000..49ad186 --- /dev/null +++ b/docs/phase8-logs/godot-models.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: Phase 4 models 59/59; 59 entries checked, 0 errors. diff --git a/docs/phase8-logs/initial-balance.log b/docs/phase8-logs/initial-balance.log new file mode 100644 index 0000000..1131e6a --- /dev/null +++ b/docs/phase8-logs/initial-balance.log @@ -0,0 +1,44 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +# Saumwacht · Balance-Sweep + +Erzeugt von `tools/balance_sim.gd`; KI-Partien mit der aktuellen +Wirtschaft und Kampfsimulation (fester 1/60-Schritt, feste Startzustände). + +## Standard gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13.3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 13.3 | 0/0 | 0/0 | 30/30 | 112/112 | 4/4 | Ja | +| 3 | 27.3 | 0/0 | 0/0 | 48/48 | 157/157 | 4/4 | Ja | +| 4 | 23.2 | 0/0 | 0/0 | 47/47 | 142/142 | 5/5 | Ja | +| 5 | 17.7 | 0/0 | 0/0 | 55/55 | 156/156 | 5/5 | Ja | +| 6 | 22.1 | 0/0 | 0/0 | 66/66 | 190/190 | 5/5 | Ja | +| 7 | 25.5 | 0/0 | 0/0 | 63/63 | 192/192 | 6/6 | Ja | +| 8 | 27.8 | 12/12 | 518/518 | 34/34 | 174/174 | 7/7 | Ja | +| 9 | 31.3 | 15/15 | 1116/1116 | 26/26 | 185/185 | 7/7 | Ja | +| 10 | 30.6 | 14/14 | 851/851 | 54/54 | 223/223 | 8/8 | Ja | +| 11 | 45.7 | 4/4 | 169/169 | 90/90 | 254/254 | 9/9 | Ja | +| 12 | 41.1 | 6/6 | 416/416 | 68/68 | 44/44 | 10/10 | Nein | + +**Ergebnis nach 12 Wellen:** Unentschieden · Kern 0/0 HP · Lecks gesamt 51/51 · mittlere Kampfdauer 26.6 s + +## Lernmodus gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13.3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 22.3 | 0/0 | 0/0 | 30/30 | 177/112 | 3/4 | Ja | +| 3 | 32.1 | 5/0 | 267/0 | 18/48 | 191/156 | 3/4 | Ja | +| 4 | 22.1 | 11/0 | 353/0 | 6/44 | 176/137 | 3/5 | Ja | +| 5 | 36.4 | 2/0 | 289/0 | 18/61 | 199/166 | 4/7 | Ja | +| 6 | 36.9 | 9/0 | 375/0 | 24/60 | 171/192 | 6/7 | Ja | +| 7 | 46.6 | 4/0 | 132/0 | 42/74 | 179/203 | 6/8 | Ja | +| 8 | 32.5 | 14/10 | 720/414 | 17/34 | 165/162 | 6/9 | Ja | +| 9 | 38.3 | 11/14 | 878/1123 | 26/20 | 25/27 | 6/10 | Nein | + +**Ergebnis nach 9 Wellen:** Front 1 gewinnt (Standard) · Kern 0/1463 HP · Lecks gesamt 56/24 · mittlere Kampfdauer 31.2 s + +Keine Verletzung der im Sweep geprüften Invarianten. +Balance-Sweep fertig in 13.7 s. diff --git a/docs/phase8-logs/linux-expedition.log b/docs/phase8-logs/linux-expedition.log new file mode 100644 index 0000000..61f030b --- /dev/null +++ b/docs/phase8-logs/linux-expedition.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 206 checks; 0 failures; report /tmp/saumwacht-phase8-linux/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/linux-short.log b/docs/phase8-logs/linux-short.log new file mode 100644 index 0000000..d4b46f3 --- /dev/null +++ b/docs/phase8-logs/linux-short.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 174 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase8-linux/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase8-logs/linux-visual.log b/docs/phase8-logs/linux-visual.log new file mode 100644 index 0000000..69ef445 --- /dev/null +++ b/docs/phase8-logs/linux-visual.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 211 checks; 0 failures; report /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/new-enemies.log b/docs/phase8-logs/new-enemies.log new file mode 100644 index 0000000..dde3626 --- /dev/null +++ b/docs/phase8-logs/new-enemies.log @@ -0,0 +1,877 @@ +00:00.013 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.013 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:53:31 | INFO: Starting glTF 2.0 export +20:53:31 | INFO: Extracting primitive: ArmL_Cuff_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Knuckle0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Knuckle1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Knuckle2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_StoneHammer_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Cuff_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Knuckle0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Knuckle1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Knuckle2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_StoneHammer_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_BackSlab0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_BackSlab1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_BackSlab2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_BackSlab3_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_BruteCore_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest0_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest0__1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest1_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest1__1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest2_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_Chest2__1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_RiftCrack_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeL0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeL1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeL2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeR0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeR1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Body_ShoulderSpikeR2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_EyeLight1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_EyeLight_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_EyeSocket1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_EyeSocket_1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_MouthSlit0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_MouthSlit1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_MouthSlit2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_Nose_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: Head_Mask_Porcelain_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_AnklePin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_HipPin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_HipPivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_HipRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_InnerShin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_KneePin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_KneePivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_KneeRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_AnklePin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_HipPin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_HipPivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_HipRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_InnerShin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_KneePin_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_KneePivot_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_KneeRim_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +20:53:31 | INFO: Primitives created: 1 +20:53:31 | INFO: Finished glTF 2.0 export in 0.15076732635498047 s + +EXPORTED e05: 41846 triangles, 125 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e05.glb +20:53:32 | INFO: Starting glTF 2.0 export +20:53:32 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_HealingKnot0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_HealingKnot1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_HealingKnot2_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_KnotRing0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_KnotRing1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_KnotRing2_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_KnotRing3_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeCore_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold2_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold3_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold4_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold5_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold6_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold7_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Body_RobeFold8_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_EyeLight1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_EyeLight_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_EyeSocket1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_EyeSocket_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_MouthSlit0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_MouthSlit1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_MouthSlit2_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_Nose_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Head_Face_Porcelain_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_KnotBranch1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_KnotBranch_1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_Staff_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffCollar0_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffCollar1_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffCollar2_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffCollar3_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffCollar4_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffHeart_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Extracting primitive: Weapon_StaffKnot_Mesh +20:53:32 | INFO: Primitives created: 1 +20:53:32 | INFO: Finished glTF 2.0 export in 0.1266188621520996 s + +EXPORTED e06: 29198 triangles, 84 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e06.glb +20:53:33 | INFO: Starting glTF 2.0 export +20:53:33 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Palm_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_Thumb_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_WristBand_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Palm_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_Thumb_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_WristBand_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:33 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +20:53:33 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_Chains1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_Chains_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask0_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask1_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask2_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask3_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CourtMask4_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CrownSpike0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CrownSpike1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CrownSpike2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CrownSpike3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_CrownSpike4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_JudgeGlow_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_JudgeHalo_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_KnotRing0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_KnotRing1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_KnotRing2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_KnotRing3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeCore_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold5_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold6_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold7_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RobeFold8_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_EyeLight1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_EyeLight_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_EyeSocket1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_EyeSocket_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_MouthSlit0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_MouthSlit1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_MouthSlit2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_Nose_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Face_Porcelain_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_KnotBranch1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_KnotBranch_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_Staff_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffCollar0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffCollar1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffCollar2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffCollar3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffCollar4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffHeart_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Weapon_StaffKnot_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Finished glTF 2.0 export in 0.14274859428405762 s + +EXPORTED e09: 38172 triangles, 135 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e09.glb +20:53:34 | INFO: Starting glTF 2.0 export +20:53:34 | INFO: Extracting primitive: Body_CrownCore_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeL0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeL1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeL2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeL3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeR0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeR1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeR2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_RidgeR3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellL0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellL1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellL2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellL3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellR0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellR1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellR2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_ShellR3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Body_Tail_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Brow1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Brow_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownBand_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem5_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownGem6_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint5_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_CrownPoint6_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Eye1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_MawRim_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_MawVoid_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_RiftThroat_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth3_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth4_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth5_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth6_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth7_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth8_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth9_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth10_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth11_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth12_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: Head_Tooth13_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Claw0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Claw1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Claw2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Inner_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Joint_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Shin_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL0_Thigh_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Claw0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Claw1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Claw2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Inner_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Joint_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Shin_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegL1_Thigh_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Claw0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Claw1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Claw2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Inner_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Joint_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Shin_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR0_Thigh_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Claw0_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Claw1_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Claw2_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Inner_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Joint_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Shin_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Extracting primitive: LegR1_Thigh_Mesh +20:53:34 | INFO: Primitives created: 1 +20:53:34 | INFO: Finished glTF 2.0 export in 0.10036635398864746 s + +EXPORTED e10: 32572 triangles, 82 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/enemy_e10.glb +PHASE4_EXPORT_PASS: 4 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase8-logs/rules.log b/docs/phase8-logs/rules.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase8-logs/rules.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase8-logs/runtime.log b/docs/phase8-logs/runtime.log new file mode 100644 index 0000000..889b69c --- /dev/null +++ b/docs/phase8-logs/runtime.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +PHASE6_RUNTIME: {"audio_events":121,"checks":9,"device":"NVIDIA GeForce RTX 5060 Ti","engine":"4.7.2-stable (fedora)","failures":[],"frames":1729,"max_draw_calls":3060,"mean_fps":144.014674337343,"mean_frame_ms":6.94373684210526,"p95_frame_ms":12.442,"renderer":"forward_plus","sample_seconds":12,"speed":2,"units_at_start":88,"viewport":"(1600.0, 960.0)","wave":20} diff --git a/docs/phase8-logs/short-regression.log b/docs/phase8-logs/short-regression.log new file mode 100644 index 0000000..73fb6ad --- /dev/null +++ b/docs/phase8-logs/short-regression.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RUNTIME_BATCHING: 3862 original parts -> 306 material surfaces across catalog assets +SLICE_MATCH: Standard gegen Lernmodus; wave 8; outcome 0; cores [3000, 1035] +SLICE_MATCH: Standard gegen Standard; wave 8; outcome -1; cores [3000, 3000] +SLICE_MATCH: Leeres Baufeld gegen Standard; wave 7; outcome 1; cores [0, 3000] +PHASE5_PASS: 373 checks; 3 real-budget matches; 0 failures diff --git a/docs/phase8-logs/tuned-balance.log b/docs/phase8-logs/tuned-balance.log new file mode 100644 index 0000000..2720ed8 --- /dev/null +++ b/docs/phase8-logs/tuned-balance.log @@ -0,0 +1,53 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +# Saumwacht · Balance-Sweep + +Erzeugt von `tools/balance_sim.gd`; KI-Partien mit der aktuellen +Wirtschaft und Kampfsimulation (fester 1/60-Schritt, feste Startzustände). + +## Standard gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13.3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 13.3 | 0/0 | 0/0 | 30/30 | 112/112 | 4/4 | Ja | +| 3 | 24.4 | 0/0 | 0/0 | 48/48 | 157/157 | 4/4 | Ja | +| 4 | 19.1 | 0/0 | 0/0 | 47/47 | 142/142 | 5/5 | Ja | +| 5 | 16.3 | 0/0 | 0/0 | 55/55 | 156/156 | 5/5 | Ja | +| 6 | 19.3 | 0/0 | 0/0 | 66/66 | 190/190 | 5/5 | Ja | +| 7 | 19.7 | 0/0 | 0/0 | 63/63 | 192/192 | 6/6 | Ja | +| 8 | 34.5 | 5/5 | 189/189 | 66/66 | 206/206 | 7/7 | Ja | +| 9 | 43.2 | 8/8 | 566/566 | 81/81 | 227/227 | 8/8 | Ja | +| 10 | 38.1 | 9/9 | 455/455 | 84/84 | 230/230 | 9/9 | Ja | +| 11 | 19.2 | 0/0 | 0/0 | 118/118 | 274/274 | 9/9 | Ja | +| 12 | 46.3 | 0/0 | 0/0 | 160/160 | 364/364 | 10/10 | Ja | +| 13 | 27.2 | 0/0 | 0/0 | 138/138 | 324/324 | 11/11 | Ja | +| 14 | 44.1 | 8/8 | 404/404 | 136/136 | 372/372 | 11/11 | Ja | +| 15 | 26.7 | 0/0 | 0/0 | 172/172 | 391/391 | 13/13 | Ja | +| 16 | 24.4 | 0/0 | 0/0 | 168/168 | 401/401 | 13/13 | Ja | +| 17 | 50.4 | 0/0 | 0/0 | 234/234 | 487/487 | 16/16 | Ja | +| 18 | 26.8 | 0/0 | 0/0 | 204/204 | 468/468 | 19/19 | Ja | +| 19 | 41.0 | 0/0 | 0/0 | 274/274 | 579/579 | 19/19 | Ja | +| 20 | 59.0 | 8/8 | 717/717 | 270/270 | 571/571 | 23/23 | Ja | + +**Ergebnis nach 20 Wellen:** Unentschieden · Kern 669/669 HP · Lecks gesamt 38/38 · mittlere Kampfdauer 30.3 s + +## Lernmodus gegen Standard + +| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet | +| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: | +| 1 | 13.3 | 0/0 | 0/0 | 24/24 | 139/139 | 3/3 | Ja | +| 2 | 21.3 | 0/0 | 0/0 | 30/30 | 177/112 | 3/4 | Ja | +| 3 | 32.8 | 4/0 | 239/0 | 24/48 | 197/156 | 3/4 | Ja | +| 4 | 23.6 | 10/0 | 325/0 | 9/44 | 185/137 | 3/5 | Ja | +| 5 | 50.1 | 2/0 | 119/0 | 18/61 | 123/166 | 5/7 | Ja | +| 6 | 51.4 | 2/0 | 94/0 | 53/60 | 164/192 | 7/7 | Ja | +| 7 | 27.6 | 0/0 | 0/0 | 63/74 | 193/203 | 7/8 | Ja | +| 8 | 37.8 | 9/0 | 497/0 | 40/90 | 202/218 | 7/9 | Ja | +| 9 | 43.5 | 12/13 | 919/962 | 46/33 | 240/187 | 7/10 | Ja | +| 10 | 35.2 | 15/0 | 814/0 | 54/72 | 60/37 | 7/10 | Nein | + +**Ergebnis nach 10 Wellen:** Front 1 gewinnt (Standard) · Kern 0/2038 HP · Lecks gesamt 54/13 · mittlere Kampfdauer 33.7 s + +Keine Verletzung der im Sweep geprüften Invarianten. +Balance-Sweep fertig in 33.3 s. diff --git a/docs/phase8-logs/visual-acceptance.log b/docs/phase8-logs/visual-acceptance.log new file mode 100644 index 0000000..1a0ce99 --- /dev/null +++ b/docs/phase8-logs/visual-acceptance.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 211 checks; 0 failures; report /home/martin/.local/share/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/windows-expedition.log b/docs/phase8-logs/windows-expedition.log new file mode 100644 index 0000000..536963d --- /dev/null +++ b/docs/phase8-logs/windows-expedition.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 206 checks; 0 failures; report /tmp/saumwacht-phase8-win/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase8-logs/windows-short.log b/docs/phase8-logs/windows-short.log new file mode 100644 index 0000000..16875dd --- /dev/null +++ b/docs/phase8-logs/windows-short.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 174 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/saumwacht-phase8-win/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase8-package-check.json b/docs/phase8-package-check.json new file mode 100644 index 0000000..c8aff68 --- /dev/null +++ b/docs/phase8-package-check.json @@ -0,0 +1,19 @@ +{ + "version": "0.8.0", + "packages": [ + { + "platform": "Linux", + "archive": "Saumwacht-Glutpakt-Linux-x64-0.8.0.zip", + "crc_ok": true, + "sha256": "43b08ed5a3ee9ca60c7f81d8458a791584436dcfd65fe985bd06c9b3d6c5cb6a", + "executable_sha256_matches": true + }, + { + "platform": "Windows", + "archive": "Saumwacht-Glutpakt-Windows-x64-0.8.0.zip", + "crc_ok": true, + "sha256": "ddbfd4a6d3bcd6ed6753a422f9107828eafd25fbde159d4bc2e8ca0d4bc64eca", + "executable_sha256_matches": true + } + ] +} diff --git a/docs/phase8-runtime.json b/docs/phase8-runtime.json new file mode 100644 index 0000000..499bc00 --- /dev/null +++ b/docs/phase8-runtime.json @@ -0,0 +1,18 @@ +{ + "audio_events": 121, + "checks": 9, + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "4.7.2-stable (fedora)", + "failures": [], + "frames": 1729, + "max_draw_calls": 3060, + "mean_fps": 144.014674337343, + "mean_frame_ms": 6.94373684210526, + "p95_frame_ms": 12.442, + "renderer": "forward_plus", + "sample_seconds": 12, + "speed": 2, + "units_at_start": 88, + "viewport": "(1600.0, 960.0)", + "wave": 20 +} \ No newline at end of file diff --git a/docs/phase8-short-balance.md b/docs/phase8-short-balance.md new file mode 100644 index 0000000..0012117 --- /dev/null +++ b/docs/phase8-short-balance.md @@ -0,0 +1,92 @@ +# Glutpakt · Daten und vollständige Testpartien + +Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler. + +## Einheiten + +Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit. + +| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit | +| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- | +| g01 | Kohlenbeißer | 45 | 260 | 17 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s. | +| g02 | Schlackenklaue | 90 | 690 | 44 | 1.2 | Klinge | Schwer | Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s. | +| g03 | Schlackenwacht | 70 | 650 | 11 | 1.2 | Klinge | Schwer | Erste 8 s: 15 % weniger erlittener Schaden. | +| g04 | Basaltbastion | 150 | 1650 | 27 | 1.4 | Klinge | Schwer | Erste 10 s: 25 % weniger Schaden, danach 10 %. | +| g05 | Funkenlanze | 65 | 240 | 24 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: 50 % zusätzlicher Grundschaden. | +| g06 | Glasballiste | 140 | 640 | 65 | 6.5 | Durchschlag | Leicht | Jeder 4. Treffer: 75 % zusätzlicher Grundschaden. | +| g07 | Aschenwerfer | 95 | 310 | 23 | 4.5 | Impuls | Leicht | Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m. | +| g08 | Kraterrufer | 190 | 820 | 58 | 5.0 | Impuls | Schwer | Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m. | +| g09 | Herdhüter | 85 | 420 | 12 | 3.5 | Impuls | Ätherisch | Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden. | +| g10 | Sonnenesse | 170 | 1080 | 30 | 4.0 | Impuls | Ätherisch | Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung. | + +## Wellen + +| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor | +| ---: | --- | --- | ---: | ---: | +| 1 | Erste Risse | 8 × Splitterling | 1.000 | 1.000 | +| 2 | Splitterstrom | 10 × Splitterling | 1.150 | 1.084 | +| 3 | Harte Schalen | 6 × Splitterling, 4 × Schalenläufer | 1.320 | 1.176 | +| 4 | Fäden im Rücken | 8 × Splitterling, 4 × Fadenschütze | 1.510 | 1.276 | +| 5 | Der Bruchhirsch | 1 × Bruchhirsch, 6 × Splitterling | 1.720 | 1.384 | +| 6 | Gepanzerter Vorstoß | 6 × Schalenläufer, 6 × Splitterling | 1.950 | 1.500 | +| 7 | Stimmen aus dem Nebel | 8 × Nebelrest, 4 × Splitterling | 2.200 | 1.624 | +| 8 | Der letzte Riegel | 1 × Riegelkoloss, 2 × Schalenläufer, 3 × Fadenschütze | 2.470 | 1.756 | + +## Standard gegen Lernmodus + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 22.3 | 3000 / 3000 | 0 / 0 | 112 / 177 | 4 / 3 | +| 3 | 32.1 | 3000 / 2733 | 0 / 5 | 156 / 191 | 4 / 3 | +| 4 | 22.1 | 3000 / 2380 | 0 / 11 | 137 / 176 | 5 / 3 | +| 5 | 36.4 | 3000 / 2091 | 0 / 2 | 166 / 199 | 7 / 4 | +| 6 | 36.9 | 3000 / 1716 | 0 / 9 | 192 / 171 | 7 / 6 | +| 7 | 46.6 | 3000 / 1584 | 0 / 4 | 193 / 179 | 8 / 6 | +| 8 | 50.0 | 3000 / 1035 | 0 / 5 | 211 / 162 | 9 / 6 | + +Ergebnis: Front 0 gewinnt. + +## Standard gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 112 / 112 | 4 / 4 | +| 3 | 27.3 | 3000 / 3000 | 0 / 0 | 157 / 157 | 4 / 4 | +| 4 | 23.2 | 3000 / 3000 | 0 / 0 | 142 / 142 | 5 / 5 | +| 5 | 17.7 | 3000 / 3000 | 0 / 0 | 156 / 156 | 5 / 5 | +| 6 | 22.1 | 3000 / 3000 | 0 / 0 | 190 / 190 | 5 / 5 | +| 7 | 20.8 | 3000 / 3000 | 0 / 0 | 182 / 182 | 6 / 6 | +| 8 | 25.0 | 3000 / 3000 | 0 / 0 | 244 / 244 | 6 / 6 | + +Ergebnis: Gleichstand. + +## Leeres Baufeld gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 295 / 139 | 0 / 3 | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 373 / 112 | 0 / 4 | +| 3 | 20.0 | 2041 / 3000 | 11 / 0 | 454 / 150 | 0 / 4 | +| 4 | 20.1 | 1584 / 3000 | 13 / 0 | 538 / 151 | 0 / 5 | +| 5 | 15.3 | 1033 / 3000 | 8 / 0 | 625 / 161 | 0 / 5 | +| 6 | 18.1 | 304 / 3000 | 13 / 0 | 715 / 187 | 0 / 5 | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 715 / 37 | 0 / 5 | + +Ergebnis: Front 1 gewinnt. + +## Nachvollziehbarer Kaufplan gegen den Lernmodus + +Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern. + +| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs | +| ---: | --- | ---: | --- | +| 1 | Schlackenwacht, Funkenlanze, Kohlenbeißer | 0 | | +| 2 | Funkenlanze | 1 | | +| 3 | Schlackenklaue ↑ | 0 | s02 | +| 4 | Funkenlanze | 1 | s01 | +| 5 | Herdhüter, Kohlenbeißer | 0 | s01 | +| 6 | Glasballiste ↑ | 0 | s02 | +| 7 | Glasballiste ↑, Kohlenbeißer | 0 | s01 | +| 8 | Glasballiste ↑, Kohlenbeißer | 0 | s02 | diff --git a/docs/phase8-short-verification.json b/docs/phase8-short-verification.json new file mode 100644 index 0000000..e3bb922 --- /dev/null +++ b/docs/phase8-short-verification.json @@ -0,0 +1,714 @@ +{ + "capture": false, + "checks": 373, + "failures": [], + "matches": [ + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 177 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 3 + ], + "seconds": 22.3333333333333, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2733 + ], + "damage": [ + 0, + 267 + ], + "gold": [ + 156, + 191 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 3 + ], + "seconds": 32.1499999999995, + "sends": [ + "s02" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 2380 + ], + "damage": [ + 0, + 353 + ], + "gold": [ + 137, + 176 + ], + "leaks": [ + 0, + 11 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 3 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2091 + ], + "damage": [ + 0, + 289 + ], + "gold": [ + 166, + 199 + ], + "leaks": [ + 0, + 2 + ], + "purchases": [ + "Herdhüter", + "Kohlenbeißer" + ], + "roster": [ + 7, + 4 + ], + "seconds": 36.4333333333325, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1716 + ], + "damage": [ + 0, + 375 + ], + "gold": [ + 192, + 171 + ], + "leaks": [ + 0, + 9 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 7, + 6 + ], + "seconds": 36.8999999999992, + "sends": [ + "s02" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1584 + ], + "damage": [ + 0, + 132 + ], + "gold": [ + 193, + 179 + ], + "leaks": [ + 0, + 4 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 8, + 6 + ], + "seconds": 46.5666666666653, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1035 + ], + "damage": [ + 0, + 549 + ], + "gold": [ + 211, + 162 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 9, + 6 + ], + "seconds": 49.9999999999984, + "sends": [ + "s02" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 112 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 157, + 157 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 4 + ], + "seconds": 27.3333333333331, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 142, + 142 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 5 + ], + "seconds": 23.25, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 156, + 156 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 17.6666666666669, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 190, + 190 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 182, + 182 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 6, + 6 + ], + "seconds": 20.7833333333334, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 244, + 244 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Basaltbastion ↑" + ], + "roster": [ + 6, + 6 + ], + "seconds": 24.9666666666665, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "damage": [ + 200, + 0 + ], + "gold": [ + 295, + 139 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "damage": [ + 270, + 0 + ], + "gold": [ + 373, + 112 + ], + "leaks": [ + 10, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "damage": [ + 489, + 0 + ], + "gold": [ + 454, + 150 + ], + "leaks": [ + 11, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 20.0333333333335, + "sends": [], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "damage": [ + 457, + 0 + ], + "gold": [ + 538, + 151 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 20.0666666666668, + "sends": [], + "wave": 4, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "damage": [ + 551, + 0 + ], + "gold": [ + 625, + 161 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 15.3333333333337, + "sends": [], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 304, + 3000 + ], + "damage": [ + 729, + 0 + ], + "gold": [ + 715, + 187 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 18.1166666666669, + "sends": [], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 0, + 3000 + ], + "damage": [ + 304, + 0 + ], + "gold": [ + 715, + 37 + ], + "leaks": [ + 12, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers_ordered": 0 + } + ] + } + ], + "wave_count": 8 +} \ No newline at end of file diff --git a/docs/phase8-verification.json b/docs/phase8-verification.json new file mode 100644 index 0000000..d9fc038 --- /dev/null +++ b/docs/phase8-verification.json @@ -0,0 +1,3174 @@ +{ + "checks": 206, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.3833333333332, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.1000000000002, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 16.2500000000004, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + } + ], + "gold": 15, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.7333333333335, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 2811, + 2811 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 17, + "leaks": [ + 5, + 5 + ], + "pending_workers": 1, + "seconds": 34.5499999999993, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2245, + 2245 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 8 + } + ], + "gold": 11, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 43.2166666666655, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 9 + } + ], + "gold": 2, + "leaks": [ + 9, + 9 + ], + "pending_workers": 0, + "seconds": 38.0666666666658, + "sends": [ + "s01", + "s01" + ], + "wave": 10, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + } + ], + "gold": 0, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.2000000000002, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 11, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + } + ], + "gold": 39, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 46.3499999999987, + "sends": [ + "s01", + "s01" + ], + "wave": 12, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 11 + } + ], + "gold": 9, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.2333333333331, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 13, + "workers": 6 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + } + ], + "gold": 44, + "leaks": [ + 8, + 8 + ], + "pending_workers": 1, + "seconds": 44.1166666666654, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 14, + "workers": 7 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 13 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.7499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 15, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + } + ], + "gold": 11, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.4333333333332, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 16, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g01", + "invested": 45, + "uid": 16 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 50.3999999999984, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 17, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g01", + "invested": 45, + "uid": 19 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.8499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 18, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + } + ], + "gold": 38, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 40.9833333333323, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 19, + "workers": 8 + }, + { + "core_hp": [ + 669, + 669 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + }, + { + "cell": [ + 3, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 20 + }, + { + "cell": [ + 1, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 21 + }, + { + "cell": [ + 4, + 3 + ], + "id": "g09", + "invested": 85, + "uid": 22 + }, + { + "cell": [ + 0, + 3 + ], + "id": "g05", + "invested": 65, + "uid": 23 + } + ], + "gold": 19, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 58.9833333333313, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 20, + "workers": 8 + } + ] + }, + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 21.3333333333334, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 2761 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 4 + ], + "pending_workers": 0, + "seconds": 32.7999999999994, + "sends": [ + "s02" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2436 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 1, + "leaks": [ + 0, + 10 + ], + "pending_workers": 1, + "seconds": 23.6333333333333, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2317 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 7, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 50.1333333333318, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 26, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 51.3833333333317, + "sends": [ + "s02" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + } + ], + "gold": 17, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.6166666666664, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 1726 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + } + ], + "gold": 8, + "leaks": [ + 0, + 9 + ], + "pending_workers": 1, + "seconds": 37.7999999999991, + "sends": [ + "s02" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2038, + 807 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 23, + "leaks": [ + 13, + 12 + ], + "pending_workers": 1, + "seconds": 43.5499999999988, + "sends": [ + "s02", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 2038, + 0 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 37, + "leaks": [ + 0, + 15 + ], + "pending_workers": 0, + "seconds": 35.1833333333326, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 10, + "workers": 6 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "formation": [], + "gold": 220, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "formation": [], + "gold": 295, + "leaks": [ + 10, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "formation": [], + "gold": 373, + "leaks": [ + 11, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [], + "wave": 3, + "workers": 1 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "formation": [], + "gold": 454, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 18.9000000000002, + "sends": [], + "wave": 4, + "workers": 1 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "formation": [], + "gold": 538, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.5166666666669, + "sends": [], + "wave": 5, + "workers": 1 + }, + { + "core_hp": [ + 304, + 3000 + ], + "formation": [], + "gold": 625, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 16.4333333333337, + "sends": [], + "wave": 6, + "workers": 1 + }, + { + "core_hp": [ + 0, + 3000 + ], + "formation": [], + "gold": 715, + "leaks": [ + 12, + 0 + ], + "pending_workers": 0, + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/phase8-visual-verification.json b/docs/phase8-visual-verification.json new file mode 100644 index 0000000..1d0e152 --- /dev/null +++ b/docs/phase8-visual-verification.json @@ -0,0 +1,3174 @@ +{ + "checks": 211, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.3833333333332, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.1000000000002, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 16.2500000000004, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + } + ], + "gold": 15, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.7333333333335, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 2811, + 2811 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 17, + "leaks": [ + 5, + 5 + ], + "pending_workers": 1, + "seconds": 34.5499999999993, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2245, + 2245 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 8 + } + ], + "gold": 11, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 43.2166666666655, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 9 + } + ], + "gold": 2, + "leaks": [ + 9, + 9 + ], + "pending_workers": 0, + "seconds": 38.0666666666658, + "sends": [ + "s01", + "s01" + ], + "wave": 10, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + } + ], + "gold": 0, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.2000000000002, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 11, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + } + ], + "gold": 39, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 46.3499999999987, + "sends": [ + "s01", + "s01" + ], + "wave": 12, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 11 + } + ], + "gold": 9, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.2333333333331, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 13, + "workers": 6 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + } + ], + "gold": 44, + "leaks": [ + 8, + 8 + ], + "pending_workers": 1, + "seconds": 44.1166666666654, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 14, + "workers": 7 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 13 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.7499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 15, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + } + ], + "gold": 11, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.4333333333332, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 16, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g01", + "invested": 45, + "uid": 16 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 50.3999999999984, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 17, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g01", + "invested": 45, + "uid": 19 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.8499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 18, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + } + ], + "gold": 38, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 40.9833333333323, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 19, + "workers": 8 + }, + { + "core_hp": [ + 669, + 669 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + }, + { + "cell": [ + 3, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 20 + }, + { + "cell": [ + 1, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 21 + }, + { + "cell": [ + 4, + 3 + ], + "id": "g09", + "invested": 85, + "uid": 22 + }, + { + "cell": [ + 0, + 3 + ], + "id": "g05", + "invested": 65, + "uid": 23 + } + ], + "gold": 19, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 58.9833333333313, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 20, + "workers": 8 + } + ] + }, + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 21.3333333333334, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 2761 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 4 + ], + "pending_workers": 0, + "seconds": 32.7999999999994, + "sends": [ + "s02" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2436 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 1, + "leaks": [ + 0, + 10 + ], + "pending_workers": 1, + "seconds": 23.6333333333333, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2317 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 7, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 50.1333333333318, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 26, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 51.3833333333317, + "sends": [ + "s02" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + } + ], + "gold": 17, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.6166666666664, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 1726 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + } + ], + "gold": 8, + "leaks": [ + 0, + 9 + ], + "pending_workers": 1, + "seconds": 37.7999999999991, + "sends": [ + "s02" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2038, + 807 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 23, + "leaks": [ + 13, + 12 + ], + "pending_workers": 1, + "seconds": 43.5499999999988, + "sends": [ + "s02", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 2038, + 0 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 37, + "leaks": [ + 0, + 15 + ], + "pending_workers": 0, + "seconds": 35.1833333333326, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 10, + "workers": 6 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "formation": [], + "gold": 220, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "formation": [], + "gold": 295, + "leaks": [ + 10, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "formation": [], + "gold": 373, + "leaks": [ + 11, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [], + "wave": 3, + "workers": 1 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "formation": [], + "gold": 454, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 18.9000000000002, + "sends": [], + "wave": 4, + "workers": 1 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "formation": [], + "gold": 538, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.5166666666669, + "sends": [], + "wave": 5, + "workers": 1 + }, + { + "core_hp": [ + 304, + 3000 + ], + "formation": [], + "gold": 625, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 16.4333333333337, + "sends": [], + "wave": 6, + "workers": 1 + }, + { + "core_hp": [ + 0, + 3000 + ], + "formation": [], + "gold": 715, + "leaks": [ + 12, + 0 + ], + "pending_workers": 0, + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/phase9-QA.md b/docs/phase9-QA.md new file mode 100644 index 0000000..d8514d0 --- /dev/null +++ b/docs/phase9-QA.md @@ -0,0 +1,65 @@ +# Wurzelbund und Bedienung · Demo 0.9.0 + +Stand: **17. September 2026**. Godot 4.7.2, Fedora/Linux, NVIDIA RTX 5060 Ti. Finalpakete nutzen das offizielle Release-Template `ed1daf0bf`. + +| Prüfung | Ergebnis | +| --- | --- | +| Wirtschaft, Kampf und Lebenszyklus | 209 bestanden | +| Glutpakt-Kurzpartie, drei reguläre Matches und Modelle | 403 bestanden | +| Glutpakt-Expedition, drei reguläre Matches | 206 bestanden | +| Finales Linux-Paket: zwei Fraktionen, Fähigkeiten, UI und vier Matches | 1.660 bestanden | +| Finales Windows-PCK mit Linux-Godot: gleiche Prüfung | 1.660 bestanden | +| Finale Pakete: Kurzpartie, Assets, Audio, Modellbetrachter, Optionen | je 274 bestanden | +| Entpackte Linux-Demo, Vulkan-Bedienprüfung | 123 bestanden | +| Entpackte Linux-Demo, OpenGL-Bedienprüfung | 123 bestanden | +| Wurzelbund-Endkampf bei 2×, Fokus, Kamera und Audio | 9 bestanden | +| GLB-Geometrie | 59/59 bestanden; 0 Topologiewarnungen | +| Godot-Import | 59/59 bestanden | +| Separat kopierte Blender-Skripte | 9/9; fremde Szene/Objekte/Materialien erhalten | +| Archive und extrahierte Programme | CRC und SHA-256 stimmen | +| Nativer Windows-Lauf | Nicht durchgeführt | + +Die vollständigen Partien verwenden ausschließlich normale Wirtschaftskommandos. Es gibt keine zusätzlichen Matchressourcen. Isolierte Fähigkeitstests setzen HP und Zeiten gezielt, ohne die späteren Partien zu verändern. Die Queue-Grenzprüfung zeigt acht Söldner-Chips mit einem reinen Darstellungssnapshot; der tatsächliche Funkenvorrat bleibt unverändert. + +## Geprüfte Bedienprobleme + +Manuelles Bauen läuft auch nach 120 simulierten Sekunden weiter; die Abrechnung wartet ebenfalls. Ein leerer Start liefert einen Bauhinweis. Der optionale Timer startet weiterhin nach 45 Sekunden. Fremde Fraktionskäufe werden vollständig abgewiesen. Beide Starter haben den richtigen Preis. Arbeiter produzieren erst in der nächsten Bauphase und lassen sich vorher vollständig zurücknehmen. Söldnerreservierung und Anzeige freier Funken stimmen überein. + +Der Test platziert über den echten Viewport-Mauspfad einen Wächter auf einem sichtbaren Feld, kontrolliert die neue Auswahl und entfernt die Modellvorschau. Die Aufwertung ist ohne Scrollen erreichbar. Wichtige Bedienelemente bleiben bei 1152 × 720 im Fenster; acht Söldner-Chips scrollen horizontal. C wechselt zwischen Front und Basis. Eine neue Partie öffnet die Fraktionsauswahl mit leerem Baufeld. Die bisherigen Tests für Optionspause, Fokus, Modellansicht und Kamerasteuerung bestehen weiter. + +## Neue Fähigkeiten und Balance + +Heilung, volle HP ohne verbrauchten Cooldown, Priorisierung verwundeter Ziele, 4-/5-Sekunden-Takte, Reichweite, Lane-Trennung und Heilungsreduktion sind geprüft. Weitere Tests decken den dritten/vierten Treffer, Zielwechsel, Keimbrand-Ticks und getrennte Brandfamilien, Bossverlangsamung, Effektablauf sowie ungebufften Flächenschaden mit korrekter Zielgrenze ab. + +| Standard-Duell | Welle | Kern-HP | +| --- | ---: | ---: | +| Wurzelbund → Glutpakt | 20 | 1.244 / 1.709 | +| Glutpakt → Wurzelbund | 20 | 1.709 / 1.244 | +| Wurzelbund → Wurzelbund | 20 | 1.244 / 1.244 | +| Wurzelbund-Spiegel, Kurzpartie | 8 | 3.000 / 3.000 | + +Die Glutpakt-Regression behält 669 / 669 nach Welle 20, Sieg gegen Lernmodus in Welle 10 und Niederlage mit leerem Feld in Welle 7. Die neue KI-Zuordnung verändert die bisherigen Glutpakt-Partien nicht. Ein Vorteil des Glutpakts in diesem festen Vergleich bleibt sichtbar; menschliche Strategien sind damit nicht abschließend ausbalanciert. + +## Laufzeit + +Wurzelbund-Spiegel, Welle 20, 86 Kampfinstanzen, 2× Tempo, 1600 × 960. Zwölf Sekunden nach zwei Sekunden Aufwärmen: **144,05 FPS im Mittel**, **6,94 ms mittlere Framezeit**, **12,88 ms im 95. Perzentil**, maximal 4.429 Draw Calls und 123 Audioereignisse. Das ist eine lokale Messung mit VSync auf einer RTX 5060 Ti. [Messdaten](phase9-runtime.json). + +## Nachweise und Wiederholung + +```bash +godot --headless --path . res://tests/test_runner.tscn +godot --headless --path . res://tools/verify_phase5.tscn -- --phase9 +godot --headless --path . -- --faction-test +godot --path . -- --faction-test --ui-only +godot --headless --path . -- --expedition-test +godot --headless --path . -- --smoke-test +godot --path . res://tools/verify_phase6_runtime.tscn -- --expedition --wurzelbund +python3 tools/verify_phase4_glb.py --json +godot --headless --path . --script res://tools/verify_phase4_models.gd +``` + +[Finale Paketprüfung](phase9-package-check.json) · [Linux-Matches](phase9-package-linux.json) · [Windows-PCK-Matches](phase9-package-windows.json) · [Vulkan-UI](phase9-package-vulkan.json) · [OpenGL-UI](phase9-package-opengl.json) · [GLB-Audit](phase9-glb-audit.json) · [Glutpakt-Kurzpartie](phase9-short-verification.json) · [Glutpakt-Expedition](phase9-glut-verification.json) · [Protokolle](phase9-logs/). + +Aufnahmen der final entpackten Demo: [Menü](screenshots/phase9/menu.png), [Bauen](screenshots/phase9/build.png), [Auswahl](screenshots/phase9/selection.png), [Basis](screenshots/phase9/base.png), [Wirtschaft](screenshots/phase9/economy.png), [Mindestfenstergröße](screenshots/phase9/minimum-window.png). Die [Welle-20-Aufnahme](screenshots/phase9/wave-20.png) stammt aus der vollständigen Grafikabnahme des Quellprojekts. + +[Start und Pakete](phase9-builds.md) · [Änderungsbericht](../../docs/phase-09-wurzelbund-und-bedienung.md) · [Historische Prüfung 0.8.0](phase8-QA.md). diff --git a/docs/phase9-builds.md b/docs/phase9-builds.md new file mode 100644 index 0000000..109676f --- /dev/null +++ b/docs/phase9-builds.md @@ -0,0 +1,52 @@ +# Demo 0.9.0 · Windows und Linux + +Stand: 17. September 2026. Enthalten: Glutpakt, Wurzelbund, 8/20-Wellen-Modus, zwei KI-Stufen, überarbeitete Bedienung, neue Arbeiter und Kristalle. + +## Herunterladen und starten + +| System | Paket | Größe | +| --- | --- | ---: | +| Linux | [Saumwacht-Linux-x64-0.9.0.zip](../../dist/Saumwacht-Linux-x64-0.9.0.zip) | 73.6 MiB | +| Windows | [Saumwacht-Windows-x64-0.9.0.zip](../../dist/Saumwacht-Windows-x64-0.9.0.zip) | 83.0 MiB | + +ZIP vollständig entpacken. Windows: `Saumwacht.exe`; Linux: `Spielen.sh` oder `Saumwacht.x86_64`. Godot und Blender werden zum Spielen nicht benötigt. Die EXE/ELF enthalten ihre Spieldaten. Die ZIPs enthalten Anleitung, Lizenzen und ein OpenGL-Startskript für Grafikprobleme. Die älteren versionierten ZIPs bleiben erhalten. + +Wurzelbund ist vorausgewählt. Nach dem Start hilft die Startformation für 185 Gold; Glutpakt kostet 180 Gold. Bauphase und Abrechnung warten auf die Leertaste. Ein Zeitlimit ist im Menü wählbar. C öffnet bzw. schließt den Blick auf Arbeiter und Kristall. F1 → Neue Partie öffnet die Fraktionsauswahl erneut. + +## Paketprüfung + +Beide Archive wurden auf CRC, SHA-256 und Hash-Gleichheit der extrahierten Programme geprüft. Die Prüfprogramme liefen aus `/tmp` außerhalb des Quellprojekts: + +- Linux-Programm: **1.660 Fraktions-/Bedien-/Matchprüfungen** und **274 Kurzpartie-/Asset-/Audio-/Modellbetrachterprüfungen**, keine Fehler. +- Windows-Spieldaten mit Linux-Godot: dieselben **1.660 + 274 Prüfungen**, keine Fehler. +- Entpacktes Linux-Programm mit Vulkan: **123 Prüfungen**, inklusive echter Mauseingabe, Aufwertung ohne Scrollen, acht Söldner-Chips und Mindestfenstergröße 1152 × 720. +- Beiliegendes Linux-Kompatibilitätsskript mit OpenGL 3.3: dieselben **123 Prüfungen**. + +**Ein nativer Windows-Lauf wurde nicht durchgeführt.** Das Windows-Paket ist ein nicht signiertes x86-64-GUI-Programm für Windows 10/11. Der PCK-Test bestätigt Spieldaten und Skripte, nicht Windows-Treiber, Audiogeräte oder den Betriebssystemstart. + +[Maschinenlesbarer Paketnachweis](phase9-package-check.json) · [Linux-Prüfung](phase9-package-linux.json) · [Windows-PCK](phase9-package-windows.json) · [Vulkan](phase9-package-vulkan.json) · [OpenGL](phase9-package-opengl.json). + +## Erstellen und reproduzieren + +Die vorhandenen offiziellen Godot-4.7.2-Release-Templates unter `assets-source/phase6/export-templates` werden verwendet. `python3 tools/build_demo.py` erstellt beide Archive und aktualisiert `dist/build-manifest.json` sowie `dist/SHA256SUMS.txt`. Quellen, Dokumentation und Entwicklungswerkzeuge sind vom Export ausgeschlossen. Alle dynamisch geladenen Assetmanifeste sind eingeschlossen. + +```bash +# Aus einem Ordner außerhalb des Projekts: +/path/to/Saumwacht.x86_64 --headless -- --faction-test +/path/to/Saumwacht.x86_64 -- --faction-test --ui-only +bash /path/to/Kompatibilitaet.sh -- --faction-test --ui-only +/path/to/Saumwacht.x86_64 --headless -- --smoke-test + +# Windows-Spieldaten, ausdrücklich kein Windows-Prozess: +godot --headless --main-pack /path/to/Saumwacht.exe -- --faction-test +godot --headless --main-pack /path/to/Saumwacht.exe -- --smoke-test +``` + +Die Tests verwenden separate temporäre Benutzerverzeichnisse. Für bestehende Spieleinstellungen bleibt der historische Benutzerordner `Saumwacht · Glutpakt` bestehen; die Fensterüberschrift lautet nun `Saumwacht · Die zwei Bünde`. Die Sandbox verhinderte beim Editor-Export den TCP-Debugserver; beide Exporte endeten erfolgreich. Die separat gestarteten Release-Prüfungen melden keine Laufzeit- oder Skriptfehler. + +## SHA-256 + +``` +46ff07ef760d07e0a84aa6cc1374b2c00ba9ebd37c36684608df9f07953c40da Saumwacht-Linux-x64-0.9.0.zip +5fb7e39e7571f1f567f4082187fbbab927b134809fe8b5a4154d5a5887032418 Saumwacht-Windows-x64-0.9.0.zip +``` diff --git a/docs/phase9-glb-audit.json b/docs/phase9-glb-audit.json new file mode 100644 index 0000000..430cf02 --- /dev/null +++ b/docs/phase9-glb-audit.json @@ -0,0 +1,7819 @@ +{ + "asset_count": 59, + "errors": [], + "assets": [ + { + "id": "g01", + "file": "unit_g01.glb", + "errors": [], + "warnings": [], + "triangles": 51844, + "mesh_parts": 131, + "primitives": 131, + "vertices": 40435, + "closed_meshes": 131, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g02", + "file": "unit_g02.glb", + "errors": [], + "warnings": [], + "triangles": 52056, + "mesh_parts": 133, + "primitives": 133, + "vertices": 40509, + "closed_meshes": 133, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0_Head", + "ArmL_Knuckle0_Seat", + "ArmL_Knuckle1_Head", + "ArmL_Knuckle1_Seat", + "ArmL_Knuckle2_Head", + "ArmL_Knuckle2_Seat", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_ShoulderTrim", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0_Head", + "ArmR_Knuckle0_Seat", + "ArmR_Knuckle1_Head", + "ArmR_Knuckle1_Seat", + "ArmR_Knuckle2_Head", + "ArmR_Knuckle2_Seat", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_ShoulderTrim", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_DorsalSpine0", + "Body_DorsalSpine1", + "Body_DorsalSpine2", + "Body_DorsalSpine3", + "Body_DorsalSpine4", + "Body_LavaCore", + "Body_Shell0_0", + "Body_Shell0_1", + "Body_Shell0_2", + "Body_Shell0_3", + "Body_Shell1_0", + "Body_Shell1_1", + "Body_Shell1_2", + "Body_Shell1_3", + "Body_Shell2_0", + "Body_Shell2_1", + "Body_Shell2_2", + "Body_Shell2_3", + "Head_BrowL", + "Head_BrowR", + "Head_CheekL", + "Head_CheekR", + "Head_Chin", + "Head_EyeL", + "Head_EyeR", + "Head_JawCavity", + "Head_LowerToothL0", + "Head_LowerToothL1", + "Head_LowerToothL2", + "Head_LowerToothL3", + "Head_LowerToothR0", + "Head_LowerToothR1", + "Head_LowerToothR2", + "Head_LowerToothR3", + "Head_MouthEmber", + "Head_UpperToothL0", + "Head_UpperToothL1", + "Head_UpperToothL2", + "Head_UpperToothL3", + "Head_UpperToothR0", + "Head_UpperToothR1", + "Head_UpperToothR2", + "Head_UpperToothR3", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "WeaponL_Claw0", + "WeaponL_Claw1", + "WeaponL_Claw2", + "WeaponR_Claw0", + "WeaponR_Claw1", + "WeaponR_Claw2" + ] + }, + { + "id": "g03", + "file": "unit_g03.glb", + "errors": [], + "warnings": [], + "triangles": 42352, + "mesh_parts": 119, + "primitives": 119, + "vertices": 31773, + "closed_meshes": 119, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g04", + "file": "unit_g04.glb", + "errors": [], + "warnings": [], + "triangles": 61340, + "mesh_parts": 220, + "primitives": 220, + "vertices": 45815, + "closed_meshes": 220, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "g05", + "file": "unit_g05.glb", + "errors": [], + "warnings": [], + "triangles": 38388, + "mesh_parts": 118, + "primitives": 118, + "vertices": 29292, + "closed_meshes": 118, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderFin", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderFin", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ChestStoneL", + "Body_ChestStoneR", + "Body_CuirassL", + "Body_CuirassR", + "Body_EmberHeart", + "Body_Spine", + "Head_Crest", + "Head_Helmet", + "Head_Neck", + "Head_Visor", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LanceCollar0", + "Weapon_LanceCollar1", + "Weapon_LanceCollar10", + "Weapon_LanceCollar2", + "Weapon_LanceCollar3", + "Weapon_LanceCollar4", + "Weapon_LanceCollar5", + "Weapon_LanceCollar6", + "Weapon_LanceCollar7", + "Weapon_LanceCollar8", + "Weapon_LanceCollar9", + "Weapon_LanceEmber", + "Weapon_LanceShaft", + "Weapon_SpearEdge1", + "Weapon_SpearEdge_1", + "Weapon_SpearHead" + ] + }, + { + "id": "g06", + "file": "unit_g06.glb", + "errors": [], + "warnings": [], + "triangles": 26884, + "mesh_parts": 85, + "primitives": 85, + "vertices": 18642, + "closed_meshes": 85, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrankInsetL", + "Body_CrankInsetR", + "Body_CrankL", + "Body_CrankR", + "Body_CrankToothL0", + "Body_CrankToothL1", + "Body_CrankToothL2", + "Body_CrankToothL3", + "Body_CrankToothL4", + "Body_CrankToothL5", + "Body_CrankToothL6", + "Body_CrankToothL7", + "Body_CrankToothR0", + "Body_CrankToothR1", + "Body_CrankToothR2", + "Body_CrankToothR3", + "Body_CrankToothR4", + "Body_CrankToothR5", + "Body_CrankToothR6", + "Body_CrankToothR7", + "Body_Gearbox", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoltHead", + "Weapon_CentralBolt", + "Weapon_DrawCableL", + "Weapon_DrawCableR", + "Weapon_GlassLimbL", + "Weapon_GlassLimbR", + "Weapon_LimbClampL", + "Weapon_LimbClampR", + "Weapon_LimbEdgeL", + "Weapon_LimbEdgeR", + "Weapon_RailL", + "Weapon_RailR", + "Weapon_RailRivet0", + "Weapon_RailRivet1", + "Weapon_RailRivet2", + "Weapon_RailRivet3", + "Weapon_RailRivet4", + "Weapon_RailRivet5", + "Weapon_RailTrimL", + "Weapon_RailTrimR", + "Weapon_RearHousing", + "Weapon_RearTrim" + ] + }, + { + "id": "g07", + "file": "unit_g07.glb", + "errors": [], + "warnings": [], + "triangles": 51284, + "mesh_parts": 128, + "primitives": 128, + "vertices": 41969, + "closed_meshes": 128, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BoulderCrust0", + "Weapon_BoulderCrust1", + "Weapon_BoulderCrust2", + "Weapon_BoulderCrust3", + "Weapon_BoulderCrust4", + "Weapon_BoulderCrust5", + "Weapon_BoulderCrust6", + "Weapon_EmberBoulder", + "Weapon_LavaPool" + ] + }, + { + "id": "g08", + "file": "unit_g08.glb", + "errors": [], + "warnings": [], + "triangles": 46922, + "mesh_parts": 123, + "primitives": 123, + "vertices": 37253, + "closed_meshes": 123, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_FrontBadge", + "Body_FrontBadgeStone", + "Body_FrontSigil", + "Body_LowerCore", + "Body_MortarBelt", + "Body_MortarBore", + "Body_MortarLip", + "Body_MortarStave0", + "Body_MortarStave1", + "Body_MortarStave10", + "Body_MortarStave11", + "Body_MortarStave2", + "Body_MortarStave3", + "Body_MortarStave4", + "Body_MortarStave5", + "Body_MortarStave6", + "Body_MortarStave7", + "Body_MortarStave8", + "Body_MortarStave9", + "Body_RimClasp0", + "Body_RimClasp1", + "Body_RimClasp10", + "Body_RimClasp11", + "Body_RimClasp2", + "Body_RimClasp3", + "Body_RimClasp4", + "Body_RimClasp5", + "Body_RimClasp6", + "Body_RimClasp7", + "Body_RimClasp8", + "Body_RimClasp9", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_LavaEddy0", + "Weapon_LavaEddy1", + "Weapon_LavaEddy2", + "Weapon_LavaPool" + ] + }, + { + "id": "g09", + "file": "unit_g09.glb", + "errors": [], + "warnings": [], + "triangles": 54596, + "mesh_parts": 173, + "primitives": 173, + "vertices": 39482, + "closed_meshes": 173, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArchStone0", + "Body_ArchStone1", + "Body_ArchStone10", + "Body_ArchStone2", + "Body_ArchStone3", + "Body_ArchStone4", + "Body_ArchStone5", + "Body_ArchStone6", + "Body_ArchStone7", + "Body_ArchStone8", + "Body_ArchStone9", + "Body_HearthBack", + "Body_HearthBrick0_0", + "Body_HearthBrick0_1", + "Body_HearthBrick0_2", + "Body_HearthBrick1_0", + "Body_HearthBrick1_1", + "Body_HearthBrick1_2", + "Body_HearthBrick2_0", + "Body_HearthBrick2_1", + "Body_HearthBrick2_2", + "Body_OvenDark", + "Body_Pillar1_0", + "Body_Pillar1_1", + "Body_Pillar_1_0", + "Body_Pillar_1_1", + "Flame_Oven0", + "Flame_Oven1", + "Flame_Oven2", + "Head_Chimney", + "Head_ChimneyCap", + "Head_ChimneyRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "g10", + "file": "unit_g10.glb", + "errors": [], + "warnings": [], + "triangles": 66734, + "mesh_parts": 223, + "primitives": 223, + "vertices": 47050, + "closed_meshes": 223, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Seal_Base", + "ArmL_Seal_Face", + "ArmL_Seal_Heart", + "ArmL_Seal_Ray0", + "ArmL_Seal_Ray1", + "ArmL_Seal_Ray10", + "ArmL_Seal_Ray11", + "ArmL_Seal_Ray2", + "ArmL_Seal_Ray3", + "ArmL_Seal_Ray4", + "ArmL_Seal_Ray5", + "ArmL_Seal_Ray6", + "ArmL_Seal_Ray7", + "ArmL_Seal_Ray8", + "ArmL_Seal_Ray9", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Seal_Base", + "ArmR_Seal_Face", + "ArmR_Seal_Heart", + "ArmR_Seal_Ray0", + "ArmR_Seal_Ray1", + "ArmR_Seal_Ray10", + "ArmR_Seal_Ray11", + "ArmR_Seal_Ray2", + "ArmR_Seal_Ray3", + "ArmR_Seal_Ray4", + "ArmR_Seal_Ray5", + "ArmR_Seal_Ray6", + "ArmR_Seal_Ray7", + "ArmR_Seal_Ray8", + "ArmR_Seal_Ray9", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HaloRay0", + "Body_HaloRay1", + "Body_HaloRay2", + "Body_HaloRay3", + "Body_HaloRay4", + "Body_HaloRay5", + "Body_HaloRay6", + "Body_HaloRay7", + "Body_HaloRay8", + "Body_HearthBack", + "Body_MantleL", + "Body_MantleR", + "Body_MantleSunL_Base", + "Body_MantleSunL_Face", + "Body_MantleSunL_Heart", + "Body_MantleSunL_Ray0", + "Body_MantleSunL_Ray1", + "Body_MantleSunL_Ray10", + "Body_MantleSunL_Ray11", + "Body_MantleSunL_Ray2", + "Body_MantleSunL_Ray3", + "Body_MantleSunL_Ray4", + "Body_MantleSunL_Ray5", + "Body_MantleSunL_Ray6", + "Body_MantleSunL_Ray7", + "Body_MantleSunL_Ray8", + "Body_MantleSunL_Ray9", + "Body_MantleSunR_Base", + "Body_MantleSunR_Face", + "Body_MantleSunR_Heart", + "Body_MantleSunR_Ray0", + "Body_MantleSunR_Ray1", + "Body_MantleSunR_Ray10", + "Body_MantleSunR_Ray11", + "Body_MantleSunR_Ray2", + "Body_MantleSunR_Ray3", + "Body_MantleSunR_Ray4", + "Body_MantleSunR_Ray5", + "Body_MantleSunR_Ray6", + "Body_MantleSunR_Ray7", + "Body_MantleSunR_Ray8", + "Body_MantleSunR_Ray9", + "Body_OvenDark", + "Body_SolarStream", + "Body_SunFrame", + "Body_SunHeart", + "Body_SunSocket", + "Body_TabardL", + "Body_TabardR", + "Body_TabardSunL_Base", + "Body_TabardSunL_Face", + "Body_TabardSunL_Heart", + "Body_TabardSunL_Ray0", + "Body_TabardSunL_Ray1", + "Body_TabardSunL_Ray10", + "Body_TabardSunL_Ray11", + "Body_TabardSunL_Ray2", + "Body_TabardSunL_Ray3", + "Body_TabardSunL_Ray4", + "Body_TabardSunL_Ray5", + "Body_TabardSunL_Ray6", + "Body_TabardSunL_Ray7", + "Body_TabardSunL_Ray8", + "Body_TabardSunL_Ray9", + "Body_TabardSunR_Base", + "Body_TabardSunR_Face", + "Body_TabardSunR_Heart", + "Body_TabardSunR_Ray0", + "Body_TabardSunR_Ray1", + "Body_TabardSunR_Ray10", + "Body_TabardSunR_Ray11", + "Body_TabardSunR_Ray2", + "Body_TabardSunR_Ray3", + "Body_TabardSunR_Ray4", + "Body_TabardSunR_Ray5", + "Body_TabardSunR_Ray6", + "Body_TabardSunR_Ray7", + "Body_TabardSunR_Ray8", + "Body_TabardSunR_Ray9", + "Flame_SolarEddy0", + "Flame_SolarEddy1", + "Flame_SolarEddy2", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_BowlRim", + "Weapon_BowlSeal_Base", + "Weapon_BowlSeal_Face", + "Weapon_BowlSeal_Heart", + "Weapon_BowlSeal_Ray0", + "Weapon_BowlSeal_Ray1", + "Weapon_BowlSeal_Ray10", + "Weapon_BowlSeal_Ray11", + "Weapon_BowlSeal_Ray2", + "Weapon_BowlSeal_Ray3", + "Weapon_BowlSeal_Ray4", + "Weapon_BowlSeal_Ray5", + "Weapon_BowlSeal_Ray6", + "Weapon_BowlSeal_Ray7", + "Weapon_BowlSeal_Ray8", + "Weapon_BowlSeal_Ray9", + "Weapon_EmberBed", + "Weapon_Flame0", + "Weapon_Flame1", + "Weapon_Flame2", + "Weapon_Flame3", + "Weapon_Flame4", + "Weapon_HearthBowl" + ] + }, + { + "id": "m01", + "file": "unit_m01.glb", + "errors": [], + "warnings": [], + "triangles": 1284, + "mesh_parts": 42, + "primitives": 42, + "vertices": 2424, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Upper", + "Body_Belt", + "Body_Chimney", + "Body_ChimneyLip", + "Body_GaugeFace", + "Body_GaugeNeedle", + "Body_PressureGauge", + "Body_RoundKettle", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m02", + "file": "unit_m02.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2552, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Fist", + "ArmL_Forearm", + "ArmL_Joint", + "ArmL_Joint_Pin", + "ArmL_Pauldron", + "ArmL_Shield_Face", + "ArmL_Shield_Rim", + "ArmL_Upper", + "ArmR_Cuff", + "ArmR_Fist", + "ArmR_Forearm", + "ArmR_Joint", + "ArmR_Joint_Pin", + "ArmR_Pauldron", + "ArmR_Shield_Face", + "ArmR_Shield_Rim", + "ArmR_Upper", + "Body_CeramicChest_Face", + "Body_CeramicChest_Rim", + "Body_HeavyChest", + "Body_PressureTankL", + "Body_PressureTankR", + "Body_TankBandL1_0", + "Body_TankBandL1_4", + "Body_TankBandR1_0", + "Body_TankBandR1_4", + "Body_ValveStemL", + "Body_ValveStemR", + "Body_ValveWheelL", + "Body_ValveWheelR", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1" + ] + }, + { + "id": "m03", + "file": "unit_m03.glb", + "errors": [], + "warnings": [], + "triangles": 932, + "mesh_parts": 43, + "primitives": 43, + "vertices": 1776, + "closed_meshes": 43, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL0_Blade1", + "WeaponR0_Blade0", + "WeaponR0_Blade1" + ] + }, + { + "id": "m04", + "file": "unit_m04.glb", + "errors": [], + "warnings": [], + "triangles": 1398, + "mesh_parts": 60, + "primitives": 60, + "vertices": 2600, + "closed_meshes": 60, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL0_Housing", + "ArmL0_Pivot", + "ArmL0_Pivot_Pin", + "ArmL0_Rod", + "ArmL1_Housing", + "ArmL1_Pivot", + "ArmL1_Pivot_Pin", + "ArmL1_Rod", + "ArmL2_Housing", + "ArmL2_Pivot", + "ArmL2_Pivot_Pin", + "ArmL2_Rod", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmR0_Housing", + "ArmR0_Pivot", + "ArmR0_Pivot_Pin", + "ArmR0_Rod", + "ArmR1_Housing", + "ArmR1_Pivot", + "ArmR1_Pivot_Pin", + "ArmR1_Rod", + "ArmR2_Housing", + "ArmR2_Pivot", + "ArmR2_Pivot_Pin", + "ArmR2_Rod", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "WeaponL0_Blade0", + "WeaponL1_Blade0", + "WeaponL2_Blade0", + "WeaponR0_Blade0", + "WeaponR1_Blade0", + "WeaponR2_Blade0" + ] + }, + { + "id": "m05", + "file": "unit_m05.glb", + "errors": [], + "warnings": [], + "triangles": 1148, + "mesh_parts": 52, + "primitives": 52, + "vertices": 2192, + "closed_meshes": 52, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Head_Scope", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m06", + "file": "unit_m06.glb", + "errors": [], + "warnings": [], + "triangles": 1432, + "mesh_parts": 66, + "primitives": 66, + "vertices": 2730, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Lower", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmL_Wrist", + "ArmL_Wrist_Pin", + "ArmR_Lower", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "ArmR_Wrist", + "ArmR_Wrist_Pin", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_Waist", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_Crossbow_Binding0", + "Weapon_Crossbow_Binding1", + "Weapon_Crossbow_Bolt", + "Weapon_Crossbow_BoltTip", + "Weapon_Crossbow_Bow1", + "Weapon_Crossbow_Bow_1", + "Weapon_Crossbow_Rail", + "Weapon_Crossbow_String1", + "Weapon_Crossbow_String_1" + ] + }, + { + "id": "m07", + "file": "unit_m07.glb", + "errors": [], + "warnings": [], + "triangles": 740, + "mesh_parts": 27, + "primitives": 27, + "vertices": 1403, + "closed_meshes": 27, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_ResonatorHousing0", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_ResonatorBell", + "Weapon_ResonatorPiston" + ] + }, + { + "id": "m08", + "file": "unit_m08.glb", + "errors": [], + "warnings": [], + "triangles": 1316, + "mesh_parts": 50, + "primitives": 50, + "vertices": 2464, + "closed_meshes": 50, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_HousingLatch0_1", + "Body_HousingLatch0__1", + "Body_HousingLatch1_1", + "Body_HousingLatch1__1", + "Body_ResonatorHousing0", + "Body_ResonatorHousing1", + "Body_SiegeChassis", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Leg2_AnkleGold", + "Leg2_Greave", + "Leg2_Knee", + "Leg2_Knee_Pin", + "Leg2_Piston", + "Leg2_Shin", + "Leg2_ThighArmor", + "Leg2_Toe0", + "Leg2_Toe1", + "Leg3_AnkleGold", + "Leg3_Greave", + "Leg3_Knee", + "Leg3_Knee_Pin", + "Leg3_Piston", + "Leg3_Shin", + "Leg3_ThighArmor", + "Leg3_Toe0", + "Leg3_Toe1", + "Weapon_DiscPiston0", + "Weapon_DiscPiston1", + "Weapon_ImpactDisc0", + "Weapon_ImpactDisc1" + ] + }, + { + "id": "m09", + "file": "unit_m09.glb", + "errors": [], + "warnings": [], + "triangles": 1160, + "mesh_parts": 51, + "primitives": 51, + "vertices": 2146, + "closed_meshes": 51, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_Shoulder_Pin", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_Shoulder_Pin", + "ArmR_Upper", + "Body_Breastplate_Face", + "Body_Breastplate_Rim", + "Body_HipPlateL", + "Body_HipPlateR", + "Body_PendulumBob", + "Body_PendulumStem", + "Body_Waist", + "Head_BrassFrame", + "Head_Ceramic", + "Head_Eye1", + "Head_Eye_1", + "Head_Mouth", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "m10", + "file": "unit_m10.glb", + "errors": [], + "warnings": [], + "triangles": 946, + "mesh_parts": 49, + "primitives": 49, + "vertices": 1828, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Elbow_Pin", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Palm", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Elbow_Pin", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Palm", + "ArmR_Upper", + "Body_Coat", + "Body_CoatGoldL", + "Body_CoatGoldR", + "Body_CreamStoleL", + "Body_CreamStoleR", + "Body_PendulumBob", + "Body_PendulumOpening", + "Body_PendulumStem", + "Head_Crown0", + "Head_Crown1", + "Head_Crown2", + "Head_Eye1", + "Head_Eye_1", + "Head_Face", + "Leg0_AnkleGold", + "Leg0_Greave", + "Leg0_Knee", + "Leg0_Knee_Pin", + "Leg0_Piston", + "Leg0_Shin", + "Leg0_ThighArmor", + "Leg0_Toe0", + "Leg0_Toe1", + "Leg1_AnkleGold", + "Leg1_Greave", + "Leg1_Knee", + "Leg1_Knee_Pin", + "Leg1_Piston", + "Leg1_Shin", + "Leg1_ThighArmor", + "Leg1_Toe0", + "Leg1_Toe1", + "Weapon_Baton" + ] + }, + { + "id": "n01", + "file": "unit_n01.glb", + "errors": [], + "warnings": [], + "triangles": 1132, + "mesh_parts": 16, + "primitives": 16, + "vertices": 3232, + "closed_meshes": 16, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Claw", + "WeaponR_Claw" + ] + }, + { + "id": "n02", + "file": "unit_n02.glb", + "errors": [], + "warnings": [], + "triangles": 1156, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3304, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_GreatShield", + "ArmL_ShieldInlay", + "ArmR", + "ArmR_GreatShield", + "ArmR_ShieldInlay", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Body_WrappedArmor0", + "Body_WrappedArmor1", + "Body_WrappedArmor2", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1" + ] + }, + { + "id": "n03", + "file": "unit_n03.glb", + "errors": [], + "warnings": [], + "triangles": 934, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2688, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "WeaponL_Sickle", + "WeaponR_Sickle" + ] + }, + { + "id": "n04", + "file": "unit_n04.glb", + "errors": [], + "warnings": [], + "triangles": 1360, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3932, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CrescentCrown", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_ShearLoopLower", + "Weapon_ShearLoopUpper", + "Weapon_ShearLower", + "Weapon_ShearPivot", + "Weapon_ShearUpper" + ] + }, + { + "id": "n05", + "file": "unit_n05.glb", + "errors": [], + "warnings": [], + "triangles": 1118, + "mesh_parts": 13, + "primitives": 13, + "vertices": 2986, + "closed_meshes": 13, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_MouthHorn", + "Weapon_MouthHorn_MintLip" + ] + }, + { + "id": "n06", + "file": "unit_n06.glb", + "errors": [], + "warnings": [], + "triangles": 1498, + "mesh_parts": 17, + "primitives": 17, + "vertices": 3844, + "closed_meshes": 17, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_HornArchL", + "Weapon_HornArchR", + "Weapon_HornL", + "Weapon_HornL_MintLip", + "Weapon_HornR", + "Weapon_HornR_MintLip" + ] + }, + { + "id": "n07", + "file": "unit_n07.glb", + "errors": [], + "warnings": [], + "triangles": 1274, + "mesh_parts": 15, + "primitives": 15, + "vertices": 3354, + "closed_meshes": 15, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmR", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Weapon_BellRim", + "Weapon_Clapper", + "Weapon_ClapperStem", + "Weapon_HangingBell" + ] + }, + { + "id": "n08", + "file": "unit_n08.glb", + "errors": [], + "warnings": [], + "triangles": 1482, + "mesh_parts": 18, + "primitives": 18, + "vertices": 3958, + "closed_meshes": 18, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Sickle", + "ArmR_Sickle", + "Body_ArchMask", + "Body_ArchMask_Eye1", + "Body_ArchMask_Eye_1", + "Body_BellSkirt", + "Body_CathedralFrontArch", + "Body_CathedralShell", + "Body_CentralFlow", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_CentralSpire", + "Head_SpireL", + "Head_SpireR", + "Weapon_Clapper", + "Weapon_ClapperChain" + ] + }, + { + "id": "n09", + "file": "unit_n09.glb", + "errors": [], + "warnings": [], + "triangles": 1314, + "mesh_parts": 24, + "primitives": 24, + "vertices": 3740, + "closed_meshes": 24, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirWisp0", + "Head_CurledHood", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "n10", + "file": "unit_n10.glb", + "errors": [], + "warnings": [], + "triangles": 1734, + "mesh_parts": 40, + "primitives": 40, + "vertices": 4872, + "closed_meshes": 40, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL", + "ArmL_Cuff", + "ArmR", + "ArmR_Cuff", + "Body_CentralFlow", + "Body_ChoirCollar0", + "Body_ChoirCollar1", + "Body_ChoirGem", + "Body_TailL", + "Body_TailR", + "Body_WispL", + "Body_WispR", + "Head_ChoirHorn0_1", + "Head_ChoirHorn0__1", + "Head_ChoirHorn1_1", + "Head_ChoirHorn1__1", + "Head_ChoirHorn2_1", + "Head_ChoirHorn2__1", + "Head_ChoirMask0", + "Head_ChoirMask0_Eye1", + "Head_ChoirMask0_Eye_1", + "Head_ChoirMask0_Mouth", + "Head_ChoirMask1", + "Head_ChoirMask1_Eye1", + "Head_ChoirMask1_Eye_1", + "Head_ChoirMask1_Mouth", + "Head_ChoirMask2", + "Head_ChoirMask2_Eye1", + "Head_ChoirMask2_Eye_1", + "Head_ChoirMask2_Mouth", + "Head_ChoirWisp0", + "Head_ChoirWisp1", + "Head_ChoirWisp2", + "Head_CurledHood", + "Head_GreatHorn1", + "Head_GreatHorn_1", + "Head_Mask", + "Head_Mask_Eye1", + "Head_Mask_Eye_1", + "Head_SingingMouth" + ] + }, + { + "id": "w01", + "file": "unit_w01.glb", + "errors": [], + "warnings": [], + "triangles": 29782, + "mesh_parts": 166, + "primitives": 166, + "vertices": 16048, + "closed_meshes": 166, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Bark0", + "Body_Bark0_Fissure0", + "Body_Bark0_Fissure1", + "Body_Bark0_Fissure2", + "Body_Bark0_Fissure3", + "Body_Bark1", + "Body_Bark1_Fissure0", + "Body_Bark1_Fissure1", + "Body_Bark1_Fissure2", + "Body_Bark1_Fissure3", + "Body_Bark2", + "Body_Bark2_Fissure0", + "Body_Bark2_Fissure1", + "Body_Bark2_Fissure2", + "Body_Bark2_Fissure3", + "Body_Bark3", + "Body_Bark3_Fissure0", + "Body_Bark3_Fissure1", + "Body_Bark3_Fissure2", + "Body_Bark3_Fissure3", + "Body_Bark4", + "Body_Bark4_Fissure0", + "Body_Bark4_Fissure1", + "Body_Bark4_Fissure2", + "Body_Bark4_Fissure3", + "Body_Bark5", + "Body_Bark5_Fissure0", + "Body_Bark5_Fissure1", + "Body_Bark5_Fissure2", + "Body_Bark5_Fissure3", + "Body_Bark6", + "Body_Bark6_Fissure0", + "Body_Bark6_Fissure1", + "Body_Bark6_Fissure2", + "Body_Bark6_Fissure3", + "Body_Bark7", + "Body_Bark7_Fissure0", + "Body_Bark7_Fissure1", + "Body_Bark7_Fissure2", + "Body_Bark7_Fissure3", + "Body_Bark8", + "Body_Bark8_Fissure0", + "Body_Bark8_Fissure1", + "Body_Bark8_Fissure2", + "Body_Bark8_Fissure3", + "Body_Blossom_Petal0", + "Body_Blossom_Petal1", + "Body_Blossom_Petal2", + "Body_Blossom_Petal3", + "Body_Blossom_Petal4", + "Body_Blossom_Pollen", + "Body_MossHeart", + "Body_ShoulderLeaf0", + "Body_ShoulderLeaf0_Midrib", + "Body_ShoulderLeaf0_Vein0_1", + "Body_ShoulderLeaf0_Vein0__1", + "Body_ShoulderLeaf0_Vein1_1", + "Body_ShoulderLeaf0_Vein1__1", + "Body_ShoulderLeaf0_Vein2_1", + "Body_ShoulderLeaf0_Vein2__1", + "Body_ShoulderLeaf1", + "Body_ShoulderLeaf1_Midrib", + "Body_ShoulderLeaf1_Vein0_1", + "Body_ShoulderLeaf1_Vein0__1", + "Body_ShoulderLeaf1_Vein1_1", + "Body_ShoulderLeaf1_Vein1__1", + "Body_ShoulderLeaf1_Vein2_1", + "Body_ShoulderLeaf1_Vein2__1", + "Body_ShoulderLeaf2", + "Body_ShoulderLeaf2_Midrib", + "Body_ShoulderLeaf2_Vein0_1", + "Body_ShoulderLeaf2_Vein0__1", + "Body_ShoulderLeaf2_Vein1_1", + "Body_ShoulderLeaf2_Vein1__1", + "Body_ShoulderLeaf2_Vein2_1", + "Body_ShoulderLeaf2_Vein2__1", + "Body_ShoulderLeaf3", + "Body_ShoulderLeaf3_Midrib", + "Body_ShoulderLeaf3_Vein0_1", + "Body_ShoulderLeaf3_Vein0__1", + "Body_ShoulderLeaf3_Vein1_1", + "Body_ShoulderLeaf3_Vein1__1", + "Body_ShoulderLeaf3_Vein2_1", + "Body_ShoulderLeaf3_Vein2__1", + "Body_Thorn0", + "Body_Thorn1", + "Body_Thorn2", + "Body_Thorn3", + "Body_Thorn4", + "Body_Thorn5", + "Body_Thorn6", + "Body_Thorn7", + "Body_Thorn8", + "Body_WovenBark0", + "Body_WovenBark0_Grain0", + "Body_WovenBark0_Grain1", + "Body_WovenBark1", + "Body_WovenBark1_Grain0", + "Body_WovenBark1_Grain1", + "Body_WovenBark2", + "Body_WovenBark2_Grain0", + "Body_WovenBark2_Grain1", + "Body_WovenBark3", + "Body_WovenBark3_Grain0", + "Body_WovenBark3_Grain1", + "Body_WovenBark4", + "Body_WovenBark4_Grain0", + "Body_WovenBark4_Grain1", + "Body_WovenBark5", + "Body_WovenBark5_Grain0", + "Body_WovenBark5_Grain1", + "Head_Eye1", + "Head_EyeShadow", + "Head_Eye_1", + "Head_Sprout1", + "Head_Sprout1_Midrib", + "Head_Sprout1_Vein0_1", + "Head_Sprout1_Vein0__1", + "Head_Sprout1_Vein1_1", + "Head_Sprout1_Vein1__1", + "Head_Sprout1_Vein2_1", + "Head_Sprout1_Vein2__1", + "Head_Sprout_1", + "Head_Sprout_1_Midrib", + "Head_Sprout_1_Vein0_1", + "Head_Sprout_1_Vein0__1", + "Head_Sprout_1_Vein1_1", + "Head_Sprout_1_Vein1__1", + "Head_Sprout_1_Vein2_1", + "Head_Sprout_1_Vein2__1", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w02", + "file": "unit_w02.glb", + "errors": [], + "warnings": [], + "triangles": 41540, + "mesh_parts": 237, + "primitives": 237, + "vertices": 21513, + "closed_meshes": 237, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_JawDark", + "Head_JawFlower_Petal0", + "Head_JawFlower_Petal1", + "Head_JawFlower_Petal2", + "Head_JawFlower_Petal3", + "Head_JawFlower_Petal4", + "Head_JawFlower_Pollen", + "Head_JawLeaf0", + "Head_JawLeaf0_Midrib", + "Head_JawLeaf0_Vein0_1", + "Head_JawLeaf0_Vein0__1", + "Head_JawLeaf0_Vein1_1", + "Head_JawLeaf0_Vein1__1", + "Head_JawLeaf0_Vein2_1", + "Head_JawLeaf0_Vein2__1", + "Head_JawLeaf1", + "Head_JawLeaf1_Midrib", + "Head_JawLeaf1_Vein0_1", + "Head_JawLeaf1_Vein0__1", + "Head_JawLeaf1_Vein1_1", + "Head_JawLeaf1_Vein1__1", + "Head_JawLeaf1_Vein2_1", + "Head_JawLeaf1_Vein2__1", + "Head_JawLeaf2", + "Head_JawLeaf2_Midrib", + "Head_JawLeaf2_Vein0_1", + "Head_JawLeaf2_Vein0__1", + "Head_JawLeaf2_Vein1_1", + "Head_JawLeaf2_Vein1__1", + "Head_JawLeaf2_Vein2_1", + "Head_JawLeaf2_Vein2__1", + "Head_JawLeaf3", + "Head_JawLeaf3_Midrib", + "Head_JawLeaf3_Vein0_1", + "Head_JawLeaf3_Vein0__1", + "Head_JawLeaf3_Vein1_1", + "Head_JawLeaf3_Vein1__1", + "Head_JawLeaf3_Vein2_1", + "Head_JawLeaf3_Vein2__1", + "Head_JawLeaf4", + "Head_JawLeaf4_Midrib", + "Head_JawLeaf4_Vein0_1", + "Head_JawLeaf4_Vein0__1", + "Head_JawLeaf4_Vein1_1", + "Head_JawLeaf4_Vein1__1", + "Head_JawLeaf4_Vein2_1", + "Head_JawLeaf4_Vein2__1", + "Head_JawLeaf5", + "Head_JawLeaf5_Midrib", + "Head_JawLeaf5_Vein0_1", + "Head_JawLeaf5_Vein0__1", + "Head_JawLeaf5_Vein1_1", + "Head_JawLeaf5_Vein1__1", + "Head_JawLeaf5_Vein2_1", + "Head_JawLeaf5_Vein2__1", + "Head_Lower_Fang0", + "Head_Lower_Fang1", + "Head_Lower_Fang2", + "Head_Lower_Fang3", + "Head_Lower_Fang4", + "Head_Lower_Fang5", + "Head_Lower_Fang6", + "Head_Lower_Fang7", + "Head_Lower_Fang8", + "Head_Lower_Jaw", + "Head_Lower_Lip0", + "Head_Lower_Lip1", + "Head_Lower_Lip2", + "Head_Upper_Fang0", + "Head_Upper_Fang1", + "Head_Upper_Fang2", + "Head_Upper_Fang3", + "Head_Upper_Fang4", + "Head_Upper_Fang5", + "Head_Upper_Fang6", + "Head_Upper_Fang7", + "Head_Upper_Fang8", + "Head_Upper_Jaw", + "Head_Upper_Lip0", + "Head_Upper_Lip1", + "Head_Upper_Lip2", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w03", + "file": "unit_w03.glb", + "errors": [], + "warnings": [], + "triangles": 50052, + "mesh_parts": 380, + "primitives": 380, + "vertices": 27619, + "closed_meshes": 380, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_Cork0_0", + "Body_Cork0_0_Fissure0", + "Body_Cork0_0_Fissure1", + "Body_Cork0_0_Fissure2", + "Body_Cork0_0_Fissure3", + "Body_Cork0_1", + "Body_Cork0_1_Fissure0", + "Body_Cork0_1_Fissure1", + "Body_Cork0_1_Fissure2", + "Body_Cork0_1_Fissure3", + "Body_Cork0_2", + "Body_Cork0_2_Fissure0", + "Body_Cork0_2_Fissure1", + "Body_Cork0_2_Fissure2", + "Body_Cork0_2_Fissure3", + "Body_Cork0_3", + "Body_Cork0_3_Fissure0", + "Body_Cork0_3_Fissure1", + "Body_Cork0_3_Fissure2", + "Body_Cork0_3_Fissure3", + "Body_Cork0_4", + "Body_Cork0_4_Fissure0", + "Body_Cork0_4_Fissure1", + "Body_Cork0_4_Fissure2", + "Body_Cork0_4_Fissure3", + "Body_Cork0_5", + "Body_Cork0_5_Fissure0", + "Body_Cork0_5_Fissure1", + "Body_Cork0_5_Fissure2", + "Body_Cork0_5_Fissure3", + "Body_Cork0_6", + "Body_Cork0_6_Fissure0", + "Body_Cork0_6_Fissure1", + "Body_Cork0_6_Fissure2", + "Body_Cork0_6_Fissure3", + "Body_Cork1_0", + "Body_Cork1_0_Fissure0", + "Body_Cork1_0_Fissure1", + "Body_Cork1_0_Fissure2", + "Body_Cork1_0_Fissure3", + "Body_Cork1_1", + "Body_Cork1_1_Fissure0", + "Body_Cork1_1_Fissure1", + "Body_Cork1_1_Fissure2", + "Body_Cork1_1_Fissure3", + "Body_Cork1_2", + "Body_Cork1_2_Fissure0", + "Body_Cork1_2_Fissure1", + "Body_Cork1_2_Fissure2", + "Body_Cork1_2_Fissure3", + "Body_Cork1_3", + "Body_Cork1_3_Fissure0", + "Body_Cork1_3_Fissure1", + "Body_Cork1_3_Fissure2", + "Body_Cork1_3_Fissure3", + "Body_Cork1_4", + "Body_Cork1_4_Fissure0", + "Body_Cork1_4_Fissure1", + "Body_Cork1_4_Fissure2", + "Body_Cork1_4_Fissure3", + "Body_Cork1_5", + "Body_Cork1_5_Fissure0", + "Body_Cork1_5_Fissure1", + "Body_Cork1_5_Fissure2", + "Body_Cork1_5_Fissure3", + "Body_Cork1_6", + "Body_Cork1_6_Fissure0", + "Body_Cork1_6_Fissure1", + "Body_Cork1_6_Fissure2", + "Body_Cork1_6_Fissure3", + "Body_Cork2_0", + "Body_Cork2_0_Fissure0", + "Body_Cork2_0_Fissure1", + "Body_Cork2_0_Fissure2", + "Body_Cork2_0_Fissure3", + "Body_Cork2_1", + "Body_Cork2_1_Fissure0", + "Body_Cork2_1_Fissure1", + "Body_Cork2_1_Fissure2", + "Body_Cork2_1_Fissure3", + "Body_Cork2_2", + "Body_Cork2_2_Fissure0", + "Body_Cork2_2_Fissure1", + "Body_Cork2_2_Fissure2", + "Body_Cork2_2_Fissure3", + "Body_Cork2_3", + "Body_Cork2_3_Fissure0", + "Body_Cork2_3_Fissure1", + "Body_Cork2_3_Fissure2", + "Body_Cork2_3_Fissure3", + "Body_Cork2_4", + "Body_Cork2_4_Fissure0", + "Body_Cork2_4_Fissure1", + "Body_Cork2_4_Fissure2", + "Body_Cork2_4_Fissure3", + "Body_Cork2_5", + "Body_Cork2_5_Fissure0", + "Body_Cork2_5_Fissure1", + "Body_Cork2_5_Fissure2", + "Body_Cork2_5_Fissure3", + "Body_Cork2_6", + "Body_Cork2_6_Fissure0", + "Body_Cork2_6_Fissure1", + "Body_Cork2_6_Fissure2", + "Body_Cork2_6_Fissure3", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen", + "Body_InnerMoss", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w04", + "file": "unit_w04.glb", + "errors": [], + "warnings": [], + "triangles": 62376, + "mesh_parts": 377, + "primitives": 377, + "vertices": 34987, + "closed_meshes": 377, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_Braid4", + "Body_Braid4_Grain0", + "Body_Braid4_Grain1", + "Body_Braid4_Grain2", + "Body_Flower0_Petal0", + "Body_Flower0_Petal1", + "Body_Flower0_Petal2", + "Body_Flower0_Petal3", + "Body_Flower0_Petal4", + "Body_Flower0_Pollen", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower2_Petal0", + "Body_Flower2_Petal1", + "Body_Flower2_Petal2", + "Body_Flower2_Petal3", + "Body_Flower2_Petal4", + "Body_Flower2_Pollen", + "Body_Flower3_Petal0", + "Body_Flower3_Petal1", + "Body_Flower3_Petal2", + "Body_Flower3_Petal3", + "Body_Flower3_Petal4", + "Body_Flower3_Pollen", + "Body_Flower4_Petal0", + "Body_Flower4_Petal1", + "Body_Flower4_Petal2", + "Body_Flower4_Petal3", + "Body_Flower4_Petal4", + "Body_Flower4_Pollen", + "Body_InnerMoss", + "Body_Log0_Bark", + "Body_Log0_Cut", + "Body_Log0_Growth0", + "Body_Log0_Growth1", + "Body_Log0_Growth2", + "Body_Log0_Growth3", + "Body_Log0_Growth4", + "Body_Log0_RoughEdge0", + "Body_Log0_RoughEdge1", + "Body_Log0_RoughEdge2", + "Body_Log0_RoughEdge3", + "Body_Log0_RoughEdge4", + "Body_Log0_RoughEdge5", + "Body_Log0_RoughEdge6", + "Body_Log0_RoughEdge7", + "Body_Log0_RoughEdge8", + "Body_Log0_RoughEdge9", + "Body_Log1_Bark", + "Body_Log1_Cut", + "Body_Log1_Growth0", + "Body_Log1_Growth1", + "Body_Log1_Growth2", + "Body_Log1_Growth3", + "Body_Log1_Growth4", + "Body_Log1_RoughEdge0", + "Body_Log1_RoughEdge1", + "Body_Log1_RoughEdge2", + "Body_Log1_RoughEdge3", + "Body_Log1_RoughEdge4", + "Body_Log1_RoughEdge5", + "Body_Log1_RoughEdge6", + "Body_Log1_RoughEdge7", + "Body_Log1_RoughEdge8", + "Body_Log1_RoughEdge9", + "Body_Log2_Bark", + "Body_Log2_Cut", + "Body_Log2_Growth0", + "Body_Log2_Growth1", + "Body_Log2_Growth2", + "Body_Log2_Growth3", + "Body_Log2_Growth4", + "Body_Log2_RoughEdge0", + "Body_Log2_RoughEdge1", + "Body_Log2_RoughEdge2", + "Body_Log2_RoughEdge3", + "Body_Log2_RoughEdge4", + "Body_Log2_RoughEdge5", + "Body_Log2_RoughEdge6", + "Body_Log2_RoughEdge7", + "Body_Log2_RoughEdge8", + "Body_Log2_RoughEdge9", + "Body_Log3_Bark", + "Body_Log3_Cut", + "Body_Log3_Growth0", + "Body_Log3_Growth1", + "Body_Log3_Growth2", + "Body_Log3_Growth3", + "Body_Log3_Growth4", + "Body_Log3_RoughEdge0", + "Body_Log3_RoughEdge1", + "Body_Log3_RoughEdge2", + "Body_Log3_RoughEdge3", + "Body_Log3_RoughEdge4", + "Body_Log3_RoughEdge5", + "Body_Log3_RoughEdge6", + "Body_Log3_RoughEdge7", + "Body_Log3_RoughEdge8", + "Body_Log3_RoughEdge9", + "Body_Log4_Bark", + "Body_Log4_Cut", + "Body_Log4_Growth0", + "Body_Log4_Growth1", + "Body_Log4_Growth2", + "Body_Log4_Growth3", + "Body_Log4_Growth4", + "Body_Log4_RoughEdge0", + "Body_Log4_RoughEdge1", + "Body_Log4_RoughEdge2", + "Body_Log4_RoughEdge3", + "Body_Log4_RoughEdge4", + "Body_Log4_RoughEdge5", + "Body_Log4_RoughEdge6", + "Body_Log4_RoughEdge7", + "Body_Log4_RoughEdge8", + "Body_Log4_RoughEdge9", + "Body_Log5_Bark", + "Body_Log5_Cut", + "Body_Log5_Growth0", + "Body_Log5_Growth1", + "Body_Log5_Growth2", + "Body_Log5_Growth3", + "Body_Log5_Growth4", + "Body_Log5_RoughEdge0", + "Body_Log5_RoughEdge1", + "Body_Log5_RoughEdge2", + "Body_Log5_RoughEdge3", + "Body_Log5_RoughEdge4", + "Body_Log5_RoughEdge5", + "Body_Log5_RoughEdge6", + "Body_Log5_RoughEdge7", + "Body_Log5_RoughEdge8", + "Body_Log5_RoughEdge9", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w05", + "file": "unit_w05.glb", + "errors": [], + "warnings": [], + "triangles": 28468, + "mesh_parts": 204, + "primitives": 204, + "vertices": 15004, + "closed_meshes": 204, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein2_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale4_Vein2__1", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Launcher_Rim", + "Head_Launcher_Shell", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w06", + "file": "unit_w06.glb", + "errors": [], + "warnings": [], + "triangles": 37768, + "mesh_parts": 296, + "primitives": 296, + "vertices": 19838, + "closed_meshes": 296, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_BroadLeaf1", + "Body_BroadLeaf1_Midrib", + "Body_BroadLeaf1_Vein0_1", + "Body_BroadLeaf1_Vein0__1", + "Body_BroadLeaf1_Vein1_1", + "Body_BroadLeaf1_Vein1__1", + "Body_BroadLeaf1_Vein2_1", + "Body_BroadLeaf1_Vein2__1", + "Body_BroadLeaf_1", + "Body_BroadLeaf_1_Midrib", + "Body_BroadLeaf_1_Vein0_1", + "Body_BroadLeaf_1_Vein0__1", + "Body_BroadLeaf_1_Vein1_1", + "Body_BroadLeaf_1_Vein1__1", + "Body_BroadLeaf_1_Vein2_1", + "Body_BroadLeaf_1_Vein2__1", + "Body_Flower1_Petal0", + "Body_Flower1_Petal1", + "Body_Flower1_Petal2", + "Body_Flower1_Petal3", + "Body_Flower1_Petal4", + "Body_Flower1_Pollen", + "Body_Flower_1_Petal0", + "Body_Flower_1_Petal1", + "Body_Flower_1_Petal2", + "Body_Flower_1_Petal3", + "Body_Flower_1_Petal4", + "Body_Flower_1_Pollen", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_LauncherScale0", + "Head_LauncherScale0_Midrib", + "Head_LauncherScale0_Vein0_1", + "Head_LauncherScale0_Vein0__1", + "Head_LauncherScale0_Vein1_1", + "Head_LauncherScale0_Vein1__1", + "Head_LauncherScale0_Vein2_1", + "Head_LauncherScale0_Vein2__1", + "Head_LauncherScale1", + "Head_LauncherScale10", + "Head_LauncherScale10_Midrib", + "Head_LauncherScale10_Vein0_1", + "Head_LauncherScale10_Vein0__1", + "Head_LauncherScale10_Vein1_1", + "Head_LauncherScale10_Vein1__1", + "Head_LauncherScale10_Vein2_1", + "Head_LauncherScale10_Vein2__1", + "Head_LauncherScale11", + "Head_LauncherScale11_Midrib", + "Head_LauncherScale11_Vein0_1", + "Head_LauncherScale11_Vein0__1", + "Head_LauncherScale11_Vein1_1", + "Head_LauncherScale11_Vein1__1", + "Head_LauncherScale11_Vein2_1", + "Head_LauncherScale11_Vein2__1", + "Head_LauncherScale1_Midrib", + "Head_LauncherScale1_Vein0_1", + "Head_LauncherScale1_Vein0__1", + "Head_LauncherScale1_Vein1_1", + "Head_LauncherScale1_Vein1__1", + "Head_LauncherScale1_Vein2_1", + "Head_LauncherScale1_Vein2__1", + "Head_LauncherScale2", + "Head_LauncherScale2_Midrib", + "Head_LauncherScale2_Vein0_1", + "Head_LauncherScale2_Vein0__1", + "Head_LauncherScale2_Vein1_1", + "Head_LauncherScale2_Vein1__1", + "Head_LauncherScale2_Vein2_1", + "Head_LauncherScale2_Vein2__1", + "Head_LauncherScale3", + "Head_LauncherScale3_Midrib", + "Head_LauncherScale3_Vein0_1", + "Head_LauncherScale3_Vein0__1", + "Head_LauncherScale3_Vein1_1", + "Head_LauncherScale3_Vein1__1", + "Head_LauncherScale3_Vein2_1", + "Head_LauncherScale3_Vein2__1", + "Head_LauncherScale4", + "Head_LauncherScale4_Midrib", + "Head_LauncherScale4_Vein0_1", + "Head_LauncherScale4_Vein0__1", + "Head_LauncherScale4_Vein1_1", + "Head_LauncherScale4_Vein1__1", + "Head_LauncherScale4_Vein2_1", + "Head_LauncherScale4_Vein2__1", + "Head_LauncherScale5", + "Head_LauncherScale5_Midrib", + "Head_LauncherScale5_Vein0_1", + "Head_LauncherScale5_Vein0__1", + "Head_LauncherScale5_Vein1_1", + "Head_LauncherScale5_Vein1__1", + "Head_LauncherScale5_Vein2_1", + "Head_LauncherScale5_Vein2__1", + "Head_LauncherScale6", + "Head_LauncherScale6_Midrib", + "Head_LauncherScale6_Vein0_1", + "Head_LauncherScale6_Vein0__1", + "Head_LauncherScale6_Vein1_1", + "Head_LauncherScale6_Vein1__1", + "Head_LauncherScale6_Vein2_1", + "Head_LauncherScale6_Vein2__1", + "Head_LauncherScale7", + "Head_LauncherScale7_Midrib", + "Head_LauncherScale7_Vein0_1", + "Head_LauncherScale7_Vein0__1", + "Head_LauncherScale7_Vein1_1", + "Head_LauncherScale7_Vein1__1", + "Head_LauncherScale7_Vein2_1", + "Head_LauncherScale7_Vein2__1", + "Head_LauncherScale8", + "Head_LauncherScale8_Midrib", + "Head_LauncherScale8_Vein0_1", + "Head_LauncherScale8_Vein0__1", + "Head_LauncherScale8_Vein1_1", + "Head_LauncherScale8_Vein1__1", + "Head_LauncherScale8_Vein2_1", + "Head_LauncherScale8_Vein2__1", + "Head_LauncherScale9", + "Head_LauncherScale9_Midrib", + "Head_LauncherScale9_Vein0_1", + "Head_LauncherScale9_Vein0__1", + "Head_LauncherScale9_Vein1_1", + "Head_LauncherScale9_Vein1__1", + "Head_LauncherScale9_Vein2_1", + "Head_LauncherScale9_Vein2__1", + "Head_Launcher_Rib0", + "Head_Launcher_Rib1", + "Head_Launcher_Rib2", + "Head_Launcher_Rib3", + "Head_Launcher_Rib4", + "Head_Launcher_Rib5", + "Head_Launcher_Rib6", + "Head_Launcher_Rib7", + "Head_Launcher_Rib8", + "Head_Launcher_Rib9", + "Head_Launcher_Rim", + "Head_Launcher_Shell", + "Head_Seed", + "Head_SeedSeam0", + "Head_SeedSeam1", + "Head_SeedSeam2", + "Head_SeedSeam3", + "Head_SeedSeam4", + "Head_SeedSeam5", + "Head_SeedSeam6", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2" + ] + }, + { + "id": "w07", + "file": "unit_w07.glb", + "errors": [], + "warnings": [], + "triangles": 46028, + "mesh_parts": 366, + "primitives": 366, + "vertices": 24069, + "closed_meshes": 366, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Shell", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Shell", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein2_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Rib0", + "Head_Cup0_Rib1", + "Head_Cup0_Rib10", + "Head_Cup0_Rib11", + "Head_Cup0_Rib2", + "Head_Cup0_Rib3", + "Head_Cup0_Rib4", + "Head_Cup0_Rib5", + "Head_Cup0_Rib6", + "Head_Cup0_Rib7", + "Head_Cup0_Rib8", + "Head_Cup0_Rib9", + "Head_Cup0_Rim", + "Head_Cup0_Shell", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4" + ] + }, + { + "id": "w08", + "file": "unit_w08.glb", + "errors": [], + "warnings": [], + "triangles": 77860, + "mesh_parts": 700, + "primitives": 700, + "vertices": 41134, + "closed_meshes": 700, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_FungalTrunk0", + "Body_FungalTrunk0_Grain0", + "Body_FungalTrunk0_Grain1", + "Body_FungalTrunk0_Grain2", + "Body_FungalTrunk0_Grain3", + "Body_FungalTrunk1", + "Body_FungalTrunk1_Grain0", + "Body_FungalTrunk1_Grain1", + "Body_FungalTrunk1_Grain2", + "Body_FungalTrunk1_Grain3", + "Body_FungalTrunk2", + "Body_FungalTrunk2_Grain0", + "Body_FungalTrunk2_Grain1", + "Body_FungalTrunk2_Grain2", + "Body_FungalTrunk2_Grain3", + "Body_SmallCup0_Fringe0", + "Body_SmallCup0_Fringe0_Midrib", + "Body_SmallCup0_Fringe0_Vein0_1", + "Body_SmallCup0_Fringe0_Vein0__1", + "Body_SmallCup0_Fringe0_Vein1_1", + "Body_SmallCup0_Fringe0_Vein1__1", + "Body_SmallCup0_Fringe0_Vein2_1", + "Body_SmallCup0_Fringe0_Vein2__1", + "Body_SmallCup0_Fringe1", + "Body_SmallCup0_Fringe1_Midrib", + "Body_SmallCup0_Fringe1_Vein0_1", + "Body_SmallCup0_Fringe1_Vein0__1", + "Body_SmallCup0_Fringe1_Vein1_1", + "Body_SmallCup0_Fringe1_Vein1__1", + "Body_SmallCup0_Fringe1_Vein2_1", + "Body_SmallCup0_Fringe1_Vein2__1", + "Body_SmallCup0_Fringe2", + "Body_SmallCup0_Fringe2_Midrib", + "Body_SmallCup0_Fringe2_Vein0_1", + "Body_SmallCup0_Fringe2_Vein0__1", + "Body_SmallCup0_Fringe2_Vein1_1", + "Body_SmallCup0_Fringe2_Vein1__1", + "Body_SmallCup0_Fringe2_Vein2_1", + "Body_SmallCup0_Fringe2_Vein2__1", + "Body_SmallCup0_Fringe3", + "Body_SmallCup0_Fringe3_Midrib", + "Body_SmallCup0_Fringe3_Vein0_1", + "Body_SmallCup0_Fringe3_Vein0__1", + "Body_SmallCup0_Fringe3_Vein1_1", + "Body_SmallCup0_Fringe3_Vein1__1", + "Body_SmallCup0_Fringe3_Vein2_1", + "Body_SmallCup0_Fringe3_Vein2__1", + "Body_SmallCup0_Fringe4", + "Body_SmallCup0_Fringe4_Midrib", + "Body_SmallCup0_Fringe4_Vein0_1", + "Body_SmallCup0_Fringe4_Vein0__1", + "Body_SmallCup0_Fringe4_Vein1_1", + "Body_SmallCup0_Fringe4_Vein1__1", + "Body_SmallCup0_Fringe4_Vein2_1", + "Body_SmallCup0_Fringe4_Vein2__1", + "Body_SmallCup0_Rib0", + "Body_SmallCup0_Rib1", + "Body_SmallCup0_Rib2", + "Body_SmallCup0_Rib3", + "Body_SmallCup0_Rib4", + "Body_SmallCup0_Rim", + "Body_SmallCup0_Shell", + "Body_SmallCup1_Fringe0", + "Body_SmallCup1_Fringe0_Midrib", + "Body_SmallCup1_Fringe0_Vein0_1", + "Body_SmallCup1_Fringe0_Vein0__1", + "Body_SmallCup1_Fringe0_Vein1_1", + "Body_SmallCup1_Fringe0_Vein1__1", + "Body_SmallCup1_Fringe0_Vein2_1", + "Body_SmallCup1_Fringe0_Vein2__1", + "Body_SmallCup1_Fringe1", + "Body_SmallCup1_Fringe1_Midrib", + "Body_SmallCup1_Fringe1_Vein0_1", + "Body_SmallCup1_Fringe1_Vein0__1", + "Body_SmallCup1_Fringe1_Vein1_1", + "Body_SmallCup1_Fringe1_Vein1__1", + "Body_SmallCup1_Fringe1_Vein2_1", + "Body_SmallCup1_Fringe1_Vein2__1", + "Body_SmallCup1_Fringe2", + "Body_SmallCup1_Fringe2_Midrib", + "Body_SmallCup1_Fringe2_Vein0_1", + "Body_SmallCup1_Fringe2_Vein0__1", + "Body_SmallCup1_Fringe2_Vein1_1", + "Body_SmallCup1_Fringe2_Vein1__1", + "Body_SmallCup1_Fringe2_Vein2_1", + "Body_SmallCup1_Fringe2_Vein2__1", + "Body_SmallCup1_Fringe3", + "Body_SmallCup1_Fringe3_Midrib", + "Body_SmallCup1_Fringe3_Vein0_1", + "Body_SmallCup1_Fringe3_Vein0__1", + "Body_SmallCup1_Fringe3_Vein1_1", + "Body_SmallCup1_Fringe3_Vein1__1", + "Body_SmallCup1_Fringe3_Vein2_1", + "Body_SmallCup1_Fringe3_Vein2__1", + "Body_SmallCup1_Fringe4", + "Body_SmallCup1_Fringe4_Midrib", + "Body_SmallCup1_Fringe4_Vein0_1", + "Body_SmallCup1_Fringe4_Vein0__1", + "Body_SmallCup1_Fringe4_Vein1_1", + "Body_SmallCup1_Fringe4_Vein1__1", + "Body_SmallCup1_Fringe4_Vein2_1", + "Body_SmallCup1_Fringe4_Vein2__1", + "Body_SmallCup1_Rib0", + "Body_SmallCup1_Rib1", + "Body_SmallCup1_Rib2", + "Body_SmallCup1_Rib3", + "Body_SmallCup1_Rib4", + "Body_SmallCup1_Rim", + "Body_SmallCup1_Shell", + "Body_SmallCup2_Fringe0", + "Body_SmallCup2_Fringe0_Midrib", + "Body_SmallCup2_Fringe0_Vein0_1", + "Body_SmallCup2_Fringe0_Vein0__1", + "Body_SmallCup2_Fringe0_Vein1_1", + "Body_SmallCup2_Fringe0_Vein1__1", + "Body_SmallCup2_Fringe0_Vein2_1", + "Body_SmallCup2_Fringe0_Vein2__1", + "Body_SmallCup2_Fringe1", + "Body_SmallCup2_Fringe1_Midrib", + "Body_SmallCup2_Fringe1_Vein0_1", + "Body_SmallCup2_Fringe1_Vein0__1", + "Body_SmallCup2_Fringe1_Vein1_1", + "Body_SmallCup2_Fringe1_Vein1__1", + "Body_SmallCup2_Fringe1_Vein2_1", + "Body_SmallCup2_Fringe1_Vein2__1", + "Body_SmallCup2_Fringe2", + "Body_SmallCup2_Fringe2_Midrib", + "Body_SmallCup2_Fringe2_Vein0_1", + "Body_SmallCup2_Fringe2_Vein0__1", + "Body_SmallCup2_Fringe2_Vein1_1", + "Body_SmallCup2_Fringe2_Vein1__1", + "Body_SmallCup2_Fringe2_Vein2_1", + "Body_SmallCup2_Fringe2_Vein2__1", + "Body_SmallCup2_Fringe3", + "Body_SmallCup2_Fringe3_Midrib", + "Body_SmallCup2_Fringe3_Vein0_1", + "Body_SmallCup2_Fringe3_Vein0__1", + "Body_SmallCup2_Fringe3_Vein1_1", + "Body_SmallCup2_Fringe3_Vein1__1", + "Body_SmallCup2_Fringe3_Vein2_1", + "Body_SmallCup2_Fringe3_Vein2__1", + "Body_SmallCup2_Fringe4", + "Body_SmallCup2_Fringe4_Midrib", + "Body_SmallCup2_Fringe4_Vein0_1", + "Body_SmallCup2_Fringe4_Vein0__1", + "Body_SmallCup2_Fringe4_Vein1_1", + "Body_SmallCup2_Fringe4_Vein1__1", + "Body_SmallCup2_Fringe4_Vein2_1", + "Body_SmallCup2_Fringe4_Vein2__1", + "Body_SmallCup2_Rib0", + "Body_SmallCup2_Rib1", + "Body_SmallCup2_Rib2", + "Body_SmallCup2_Rib3", + "Body_SmallCup2_Rib4", + "Body_SmallCup2_Rim", + "Body_SmallCup2_Shell", + "Body_SmallCup3_Fringe0", + "Body_SmallCup3_Fringe0_Midrib", + "Body_SmallCup3_Fringe0_Vein0_1", + "Body_SmallCup3_Fringe0_Vein0__1", + "Body_SmallCup3_Fringe0_Vein1_1", + "Body_SmallCup3_Fringe0_Vein1__1", + "Body_SmallCup3_Fringe0_Vein2_1", + "Body_SmallCup3_Fringe0_Vein2__1", + "Body_SmallCup3_Fringe1", + "Body_SmallCup3_Fringe1_Midrib", + "Body_SmallCup3_Fringe1_Vein0_1", + "Body_SmallCup3_Fringe1_Vein0__1", + "Body_SmallCup3_Fringe1_Vein1_1", + "Body_SmallCup3_Fringe1_Vein1__1", + "Body_SmallCup3_Fringe1_Vein2_1", + "Body_SmallCup3_Fringe1_Vein2__1", + "Body_SmallCup3_Fringe2", + "Body_SmallCup3_Fringe2_Midrib", + "Body_SmallCup3_Fringe2_Vein0_1", + "Body_SmallCup3_Fringe2_Vein0__1", + "Body_SmallCup3_Fringe2_Vein1_1", + "Body_SmallCup3_Fringe2_Vein1__1", + "Body_SmallCup3_Fringe2_Vein2_1", + "Body_SmallCup3_Fringe2_Vein2__1", + "Body_SmallCup3_Fringe3", + "Body_SmallCup3_Fringe3_Midrib", + "Body_SmallCup3_Fringe3_Vein0_1", + "Body_SmallCup3_Fringe3_Vein0__1", + "Body_SmallCup3_Fringe3_Vein1_1", + "Body_SmallCup3_Fringe3_Vein1__1", + "Body_SmallCup3_Fringe3_Vein2_1", + "Body_SmallCup3_Fringe3_Vein2__1", + "Body_SmallCup3_Fringe4", + "Body_SmallCup3_Fringe4_Midrib", + "Body_SmallCup3_Fringe4_Vein0_1", + "Body_SmallCup3_Fringe4_Vein0__1", + "Body_SmallCup3_Fringe4_Vein1_1", + "Body_SmallCup3_Fringe4_Vein1__1", + "Body_SmallCup3_Fringe4_Vein2_1", + "Body_SmallCup3_Fringe4_Vein2__1", + "Body_SmallCup3_Rib0", + "Body_SmallCup3_Rib1", + "Body_SmallCup3_Rib2", + "Body_SmallCup3_Rib3", + "Body_SmallCup3_Rib4", + "Body_SmallCup3_Rim", + "Body_SmallCup3_Shell", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Cup0_Fringe0", + "Head_Cup0_Fringe0_Midrib", + "Head_Cup0_Fringe0_Vein0_1", + "Head_Cup0_Fringe0_Vein0__1", + "Head_Cup0_Fringe0_Vein1_1", + "Head_Cup0_Fringe0_Vein1__1", + "Head_Cup0_Fringe0_Vein2_1", + "Head_Cup0_Fringe0_Vein2__1", + "Head_Cup0_Fringe1", + "Head_Cup0_Fringe10", + "Head_Cup0_Fringe10_Midrib", + "Head_Cup0_Fringe10_Vein0_1", + "Head_Cup0_Fringe10_Vein0__1", + "Head_Cup0_Fringe10_Vein1_1", + "Head_Cup0_Fringe10_Vein1__1", + "Head_Cup0_Fringe10_Vein2_1", + "Head_Cup0_Fringe10_Vein2__1", + "Head_Cup0_Fringe11", + "Head_Cup0_Fringe11_Midrib", + "Head_Cup0_Fringe11_Vein0_1", + "Head_Cup0_Fringe11_Vein0__1", + "Head_Cup0_Fringe11_Vein1_1", + "Head_Cup0_Fringe11_Vein1__1", + "Head_Cup0_Fringe11_Vein2_1", + "Head_Cup0_Fringe11_Vein2__1", + "Head_Cup0_Fringe1_Midrib", + "Head_Cup0_Fringe1_Vein0_1", + "Head_Cup0_Fringe1_Vein0__1", + "Head_Cup0_Fringe1_Vein1_1", + "Head_Cup0_Fringe1_Vein1__1", + "Head_Cup0_Fringe1_Vein2_1", + "Head_Cup0_Fringe1_Vein2__1", + "Head_Cup0_Fringe2", + "Head_Cup0_Fringe2_Midrib", + "Head_Cup0_Fringe2_Vein0_1", + "Head_Cup0_Fringe2_Vein0__1", + "Head_Cup0_Fringe2_Vein1_1", + "Head_Cup0_Fringe2_Vein1__1", + "Head_Cup0_Fringe2_Vein2_1", + "Head_Cup0_Fringe2_Vein2__1", + "Head_Cup0_Fringe3", + "Head_Cup0_Fringe3_Midrib", + "Head_Cup0_Fringe3_Vein0_1", + "Head_Cup0_Fringe3_Vein0__1", + "Head_Cup0_Fringe3_Vein1_1", + "Head_Cup0_Fringe3_Vein1__1", + "Head_Cup0_Fringe3_Vein2_1", + "Head_Cup0_Fringe3_Vein2__1", + "Head_Cup0_Fringe4", + "Head_Cup0_Fringe4_Midrib", + "Head_Cup0_Fringe4_Vein0_1", + "Head_Cup0_Fringe4_Vein0__1", + "Head_Cup0_Fringe4_Vein1_1", + "Head_Cup0_Fringe4_Vein1__1", + "Head_Cup0_Fringe4_Vein2_1", + "Head_Cup0_Fringe4_Vein2__1", + "Head_Cup0_Fringe5", + "Head_Cup0_Fringe5_Midrib", + "Head_Cup0_Fringe5_Vein0_1", + "Head_Cup0_Fringe5_Vein0__1", + "Head_Cup0_Fringe5_Vein1_1", + "Head_Cup0_Fringe5_Vein1__1", + "Head_Cup0_Fringe5_Vein2_1", + "Head_Cup0_Fringe5_Vein2__1", + "Head_Cup0_Fringe6", + "Head_Cup0_Fringe6_Midrib", + "Head_Cup0_Fringe6_Vein0_1", + "Head_Cup0_Fringe6_Vein0__1", + "Head_Cup0_Fringe6_Vein1_1", + "Head_Cup0_Fringe6_Vein1__1", + "Head_Cup0_Fringe6_Vein2_1", + "Head_Cup0_Fringe6_Vein2__1", + "Head_Cup0_Fringe7", + "Head_Cup0_Fringe7_Midrib", + "Head_Cup0_Fringe7_Vein0_1", + "Head_Cup0_Fringe7_Vein0__1", + "Head_Cup0_Fringe7_Vein1_1", + "Head_Cup0_Fringe7_Vein1__1", + "Head_Cup0_Fringe7_Vein2_1", + "Head_Cup0_Fringe7_Vein2__1", + "Head_Cup0_Fringe8", + "Head_Cup0_Fringe8_Midrib", + "Head_Cup0_Fringe8_Vein0_1", + "Head_Cup0_Fringe8_Vein0__1", + "Head_Cup0_Fringe8_Vein1_1", + "Head_Cup0_Fringe8_Vein1__1", + "Head_Cup0_Fringe8_Vein2_1", + "Head_Cup0_Fringe8_Vein2__1", + "Head_Cup0_Fringe9", + "Head_Cup0_Fringe9_Midrib", + "Head_Cup0_Fringe9_Vein0_1", + "Head_Cup0_Fringe9_Vein0__1", + "Head_Cup0_Fringe9_Vein1_1", + "Head_Cup0_Fringe9_Vein1__1", + "Head_Cup0_Fringe9_Vein2_1", + "Head_Cup0_Fringe9_Vein2__1", + "Head_Cup0_Rib0", + "Head_Cup0_Rib1", + "Head_Cup0_Rib10", + "Head_Cup0_Rib11", + "Head_Cup0_Rib2", + "Head_Cup0_Rib3", + "Head_Cup0_Rib4", + "Head_Cup0_Rib5", + "Head_Cup0_Rib6", + "Head_Cup0_Rib7", + "Head_Cup0_Rib8", + "Head_Cup0_Rib9", + "Head_Cup0_Rim", + "Head_Cup0_Shell", + "Head_Cup1_Fringe0", + "Head_Cup1_Fringe0_Midrib", + "Head_Cup1_Fringe0_Vein0_1", + "Head_Cup1_Fringe0_Vein0__1", + "Head_Cup1_Fringe0_Vein1_1", + "Head_Cup1_Fringe0_Vein1__1", + "Head_Cup1_Fringe0_Vein2_1", + "Head_Cup1_Fringe0_Vein2__1", + "Head_Cup1_Fringe1", + "Head_Cup1_Fringe10", + "Head_Cup1_Fringe10_Midrib", + "Head_Cup1_Fringe10_Vein0_1", + "Head_Cup1_Fringe10_Vein0__1", + "Head_Cup1_Fringe10_Vein1_1", + "Head_Cup1_Fringe10_Vein1__1", + "Head_Cup1_Fringe10_Vein2_1", + "Head_Cup1_Fringe10_Vein2__1", + "Head_Cup1_Fringe11", + "Head_Cup1_Fringe11_Midrib", + "Head_Cup1_Fringe11_Vein0_1", + "Head_Cup1_Fringe11_Vein0__1", + "Head_Cup1_Fringe11_Vein1_1", + "Head_Cup1_Fringe11_Vein1__1", + "Head_Cup1_Fringe11_Vein2_1", + "Head_Cup1_Fringe11_Vein2__1", + "Head_Cup1_Fringe1_Midrib", + "Head_Cup1_Fringe1_Vein0_1", + "Head_Cup1_Fringe1_Vein0__1", + "Head_Cup1_Fringe1_Vein1_1", + "Head_Cup1_Fringe1_Vein1__1", + "Head_Cup1_Fringe1_Vein2_1", + "Head_Cup1_Fringe1_Vein2__1", + "Head_Cup1_Fringe2", + "Head_Cup1_Fringe2_Midrib", + "Head_Cup1_Fringe2_Vein0_1", + "Head_Cup1_Fringe2_Vein0__1", + "Head_Cup1_Fringe2_Vein1_1", + "Head_Cup1_Fringe2_Vein1__1", + "Head_Cup1_Fringe2_Vein2_1", + "Head_Cup1_Fringe2_Vein2__1", + "Head_Cup1_Fringe3", + "Head_Cup1_Fringe3_Midrib", + "Head_Cup1_Fringe3_Vein0_1", + "Head_Cup1_Fringe3_Vein0__1", + "Head_Cup1_Fringe3_Vein1_1", + "Head_Cup1_Fringe3_Vein1__1", + "Head_Cup1_Fringe3_Vein2_1", + "Head_Cup1_Fringe3_Vein2__1", + "Head_Cup1_Fringe4", + "Head_Cup1_Fringe4_Midrib", + "Head_Cup1_Fringe4_Vein0_1", + "Head_Cup1_Fringe4_Vein0__1", + "Head_Cup1_Fringe4_Vein1_1", + "Head_Cup1_Fringe4_Vein1__1", + "Head_Cup1_Fringe4_Vein2_1", + "Head_Cup1_Fringe4_Vein2__1", + "Head_Cup1_Fringe5", + "Head_Cup1_Fringe5_Midrib", + "Head_Cup1_Fringe5_Vein0_1", + "Head_Cup1_Fringe5_Vein0__1", + "Head_Cup1_Fringe5_Vein1_1", + "Head_Cup1_Fringe5_Vein1__1", + "Head_Cup1_Fringe5_Vein2_1", + "Head_Cup1_Fringe5_Vein2__1", + "Head_Cup1_Fringe6", + "Head_Cup1_Fringe6_Midrib", + "Head_Cup1_Fringe6_Vein0_1", + "Head_Cup1_Fringe6_Vein0__1", + "Head_Cup1_Fringe6_Vein1_1", + "Head_Cup1_Fringe6_Vein1__1", + "Head_Cup1_Fringe6_Vein2_1", + "Head_Cup1_Fringe6_Vein2__1", + "Head_Cup1_Fringe7", + "Head_Cup1_Fringe7_Midrib", + "Head_Cup1_Fringe7_Vein0_1", + "Head_Cup1_Fringe7_Vein0__1", + "Head_Cup1_Fringe7_Vein1_1", + "Head_Cup1_Fringe7_Vein1__1", + "Head_Cup1_Fringe7_Vein2_1", + "Head_Cup1_Fringe7_Vein2__1", + "Head_Cup1_Fringe8", + "Head_Cup1_Fringe8_Midrib", + "Head_Cup1_Fringe8_Vein0_1", + "Head_Cup1_Fringe8_Vein0__1", + "Head_Cup1_Fringe8_Vein1_1", + "Head_Cup1_Fringe8_Vein1__1", + "Head_Cup1_Fringe8_Vein2_1", + "Head_Cup1_Fringe8_Vein2__1", + "Head_Cup1_Fringe9", + "Head_Cup1_Fringe9_Midrib", + "Head_Cup1_Fringe9_Vein0_1", + "Head_Cup1_Fringe9_Vein0__1", + "Head_Cup1_Fringe9_Vein1_1", + "Head_Cup1_Fringe9_Vein1__1", + "Head_Cup1_Fringe9_Vein2_1", + "Head_Cup1_Fringe9_Vein2__1", + "Head_Cup1_Rib0", + "Head_Cup1_Rib1", + "Head_Cup1_Rib10", + "Head_Cup1_Rib11", + "Head_Cup1_Rib2", + "Head_Cup1_Rib3", + "Head_Cup1_Rib4", + "Head_Cup1_Rib5", + "Head_Cup1_Rib6", + "Head_Cup1_Rib7", + "Head_Cup1_Rib8", + "Head_Cup1_Rib9", + "Head_Cup1_Rim", + "Head_Cup1_Shell", + "Head_Cup2_Fringe0", + "Head_Cup2_Fringe0_Midrib", + "Head_Cup2_Fringe0_Vein0_1", + "Head_Cup2_Fringe0_Vein0__1", + "Head_Cup2_Fringe0_Vein1_1", + "Head_Cup2_Fringe0_Vein1__1", + "Head_Cup2_Fringe0_Vein2_1", + "Head_Cup2_Fringe0_Vein2__1", + "Head_Cup2_Fringe1", + "Head_Cup2_Fringe10", + "Head_Cup2_Fringe10_Midrib", + "Head_Cup2_Fringe10_Vein0_1", + "Head_Cup2_Fringe10_Vein0__1", + "Head_Cup2_Fringe10_Vein1_1", + "Head_Cup2_Fringe10_Vein1__1", + "Head_Cup2_Fringe10_Vein2_1", + "Head_Cup2_Fringe10_Vein2__1", + "Head_Cup2_Fringe11", + "Head_Cup2_Fringe11_Midrib", + "Head_Cup2_Fringe11_Vein0_1", + "Head_Cup2_Fringe11_Vein0__1", + "Head_Cup2_Fringe11_Vein1_1", + "Head_Cup2_Fringe11_Vein1__1", + "Head_Cup2_Fringe11_Vein2_1", + "Head_Cup2_Fringe11_Vein2__1", + "Head_Cup2_Fringe1_Midrib", + "Head_Cup2_Fringe1_Vein0_1", + "Head_Cup2_Fringe1_Vein0__1", + "Head_Cup2_Fringe1_Vein1_1", + "Head_Cup2_Fringe1_Vein1__1", + "Head_Cup2_Fringe1_Vein2_1", + "Head_Cup2_Fringe1_Vein2__1", + "Head_Cup2_Fringe2", + "Head_Cup2_Fringe2_Midrib", + "Head_Cup2_Fringe2_Vein0_1", + "Head_Cup2_Fringe2_Vein0__1", + "Head_Cup2_Fringe2_Vein1_1", + "Head_Cup2_Fringe2_Vein1__1", + "Head_Cup2_Fringe2_Vein2_1", + "Head_Cup2_Fringe2_Vein2__1", + "Head_Cup2_Fringe3", + "Head_Cup2_Fringe3_Midrib", + "Head_Cup2_Fringe3_Vein0_1", + "Head_Cup2_Fringe3_Vein0__1", + "Head_Cup2_Fringe3_Vein1_1", + "Head_Cup2_Fringe3_Vein1__1", + "Head_Cup2_Fringe3_Vein2_1", + "Head_Cup2_Fringe3_Vein2__1", + "Head_Cup2_Fringe4", + "Head_Cup2_Fringe4_Midrib", + "Head_Cup2_Fringe4_Vein0_1", + "Head_Cup2_Fringe4_Vein0__1", + "Head_Cup2_Fringe4_Vein1_1", + "Head_Cup2_Fringe4_Vein1__1", + "Head_Cup2_Fringe4_Vein2_1", + "Head_Cup2_Fringe4_Vein2__1", + "Head_Cup2_Fringe5", + "Head_Cup2_Fringe5_Midrib", + "Head_Cup2_Fringe5_Vein0_1", + "Head_Cup2_Fringe5_Vein0__1", + "Head_Cup2_Fringe5_Vein1_1", + "Head_Cup2_Fringe5_Vein1__1", + "Head_Cup2_Fringe5_Vein2_1", + "Head_Cup2_Fringe5_Vein2__1", + "Head_Cup2_Fringe6", + "Head_Cup2_Fringe6_Midrib", + "Head_Cup2_Fringe6_Vein0_1", + "Head_Cup2_Fringe6_Vein0__1", + "Head_Cup2_Fringe6_Vein1_1", + "Head_Cup2_Fringe6_Vein1__1", + "Head_Cup2_Fringe6_Vein2_1", + "Head_Cup2_Fringe6_Vein2__1", + "Head_Cup2_Fringe7", + "Head_Cup2_Fringe7_Midrib", + "Head_Cup2_Fringe7_Vein0_1", + "Head_Cup2_Fringe7_Vein0__1", + "Head_Cup2_Fringe7_Vein1_1", + "Head_Cup2_Fringe7_Vein1__1", + "Head_Cup2_Fringe7_Vein2_1", + "Head_Cup2_Fringe7_Vein2__1", + "Head_Cup2_Fringe8", + "Head_Cup2_Fringe8_Midrib", + "Head_Cup2_Fringe8_Vein0_1", + "Head_Cup2_Fringe8_Vein0__1", + "Head_Cup2_Fringe8_Vein1_1", + "Head_Cup2_Fringe8_Vein1__1", + "Head_Cup2_Fringe8_Vein2_1", + "Head_Cup2_Fringe8_Vein2__1", + "Head_Cup2_Fringe9", + "Head_Cup2_Fringe9_Midrib", + "Head_Cup2_Fringe9_Vein0_1", + "Head_Cup2_Fringe9_Vein0__1", + "Head_Cup2_Fringe9_Vein1_1", + "Head_Cup2_Fringe9_Vein1__1", + "Head_Cup2_Fringe9_Vein2_1", + "Head_Cup2_Fringe9_Vein2__1", + "Head_Cup2_Rib0", + "Head_Cup2_Rib1", + "Head_Cup2_Rib10", + "Head_Cup2_Rib11", + "Head_Cup2_Rib2", + "Head_Cup2_Rib3", + "Head_Cup2_Rib4", + "Head_Cup2_Rib5", + "Head_Cup2_Rib6", + "Head_Cup2_Rib7", + "Head_Cup2_Rib8", + "Head_Cup2_Rib9", + "Head_Cup2_Rim", + "Head_Cup2_Shell", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Spore0_0", + "Weapon_Spore0_1", + "Weapon_Spore0_2", + "Weapon_Spore0_3", + "Weapon_Spore0_4", + "Weapon_Spore1_0", + "Weapon_Spore1_1", + "Weapon_Spore1_2", + "Weapon_Spore1_3", + "Weapon_Spore1_4", + "Weapon_Spore2_0", + "Weapon_Spore2_1", + "Weapon_Spore2_2", + "Weapon_Spore2_3", + "Weapon_Spore2_4" + ] + }, + { + "id": "w09", + "file": "unit_w09.glb", + "errors": [], + "warnings": [], + "triangles": 30280, + "mesh_parts": 199, + "primitives": 199, + "vertices": 16346, + "closed_meshes": 199, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Braid0", + "Body_Braid0_Grain0", + "Body_Braid0_Grain1", + "Body_Braid0_Grain2", + "Body_Braid1", + "Body_Braid1_Grain0", + "Body_Braid1_Grain1", + "Body_Braid1_Grain2", + "Body_Braid2", + "Body_Braid2_Grain0", + "Body_Braid2_Grain1", + "Body_Braid2_Grain2", + "Body_Braid3", + "Body_Braid3_Grain0", + "Body_Braid3_Grain1", + "Body_Braid3_Grain2", + "Body_TrunkLeaf0", + "Body_TrunkLeaf0_Midrib", + "Body_TrunkLeaf0_Vein0_1", + "Body_TrunkLeaf0_Vein0__1", + "Body_TrunkLeaf0_Vein1_1", + "Body_TrunkLeaf0_Vein1__1", + "Body_TrunkLeaf0_Vein2_1", + "Body_TrunkLeaf0_Vein2__1", + "Body_TrunkLeaf1", + "Body_TrunkLeaf1_Midrib", + "Body_TrunkLeaf1_Vein0_1", + "Body_TrunkLeaf1_Vein0__1", + "Body_TrunkLeaf1_Vein1_1", + "Body_TrunkLeaf1_Vein1__1", + "Body_TrunkLeaf1_Vein2_1", + "Body_TrunkLeaf1_Vein2__1", + "Body_TrunkLeaf2", + "Body_TrunkLeaf2_Midrib", + "Body_TrunkLeaf2_Vein0_1", + "Body_TrunkLeaf2_Vein0__1", + "Body_TrunkLeaf2_Vein1_1", + "Body_TrunkLeaf2_Vein1__1", + "Body_TrunkLeaf2_Vein2_1", + "Body_TrunkLeaf2_Vein2__1", + "Body_TrunkLeaf3", + "Body_TrunkLeaf3_Midrib", + "Body_TrunkLeaf3_Vein0_1", + "Body_TrunkLeaf3_Vein0__1", + "Body_TrunkLeaf3_Vein1_1", + "Body_TrunkLeaf3_Vein1__1", + "Body_TrunkLeaf3_Vein2_1", + "Body_TrunkLeaf3_Vein2__1", + "Body_TrunkLeaf4", + "Body_TrunkLeaf4_Midrib", + "Body_TrunkLeaf4_Vein0_1", + "Body_TrunkLeaf4_Vein0__1", + "Body_TrunkLeaf4_Vein1_1", + "Body_TrunkLeaf4_Vein1__1", + "Body_TrunkLeaf4_Vein2_1", + "Body_TrunkLeaf4_Vein2__1", + "Body_TrunkLeaf5", + "Body_TrunkLeaf5_Midrib", + "Body_TrunkLeaf5_Vein0_1", + "Body_TrunkLeaf5_Vein0__1", + "Body_TrunkLeaf5_Vein1_1", + "Body_TrunkLeaf5_Vein1__1", + "Body_TrunkLeaf5_Vein2_1", + "Body_TrunkLeaf5_Vein2__1", + "Body_TrunkLeaf6", + "Body_TrunkLeaf6_Midrib", + "Body_TrunkLeaf6_Vein0_1", + "Body_TrunkLeaf6_Vein0__1", + "Body_TrunkLeaf6_Vein1_1", + "Body_TrunkLeaf6_Vein1__1", + "Body_TrunkLeaf6_Vein2_1", + "Body_TrunkLeaf6_Vein2__1", + "Body_TrunkLeaf7", + "Body_TrunkLeaf7_Midrib", + "Body_TrunkLeaf7_Vein0_1", + "Body_TrunkLeaf7_Vein0__1", + "Body_TrunkLeaf7_Vein1_1", + "Body_TrunkLeaf7_Vein1__1", + "Body_TrunkLeaf7_Vein2_1", + "Body_TrunkLeaf7_Vein2__1", + "Head_Crown0", + "Head_Crown0_Midrib", + "Head_Crown0_Vein0_1", + "Head_Crown0_Vein0__1", + "Head_Crown0_Vein1_1", + "Head_Crown0_Vein1__1", + "Head_Crown0_Vein2_1", + "Head_Crown0_Vein2__1", + "Head_Crown1", + "Head_Crown1_Midrib", + "Head_Crown1_Vein0_1", + "Head_Crown1_Vein0__1", + "Head_Crown1_Vein1_1", + "Head_Crown1_Vein1__1", + "Head_Crown1_Vein2_1", + "Head_Crown1_Vein2__1", + "Head_Crown2", + "Head_Crown2_Midrib", + "Head_Crown2_Vein0_1", + "Head_Crown2_Vein0__1", + "Head_Crown2_Vein1_1", + "Head_Crown2_Vein1__1", + "Head_Crown2_Vein2_1", + "Head_Crown2_Vein2__1", + "Head_Crown3", + "Head_Crown3_Midrib", + "Head_Crown3_Vein0_1", + "Head_Crown3_Vein0__1", + "Head_Crown3_Vein1_1", + "Head_Crown3_Vein1__1", + "Head_Crown3_Vein2_1", + "Head_Crown3_Vein2__1", + "Head_Crown4", + "Head_Crown4_Midrib", + "Head_Crown4_Vein0_1", + "Head_Crown4_Vein0__1", + "Head_Crown4_Vein1_1", + "Head_Crown4_Vein1__1", + "Head_Crown4_Vein2_1", + "Head_Crown4_Vein2__1", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Basin_Rim", + "Weapon_Basin_Shell", + "Weapon_DewOrb", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_Water" + ] + }, + { + "id": "w10", + "file": "unit_w10.glb", + "errors": [], + "warnings": [], + "triangles": 40508, + "mesh_parts": 348, + "primitives": 348, + "vertices": 22095, + "closed_meshes": 348, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_BasinVine", + "ArmL_BasinVine_Grain0", + "ArmL_BasinVine_Grain1", + "ArmL_BasinVine_Grain2", + "ArmR_BasinVine", + "ArmR_BasinVine_Grain0", + "ArmR_BasinVine_Grain1", + "ArmR_BasinVine_Grain2", + "Body_Arch1_0", + "Body_Arch1_0_Grain0", + "Body_Arch1_0_Grain1", + "Body_Arch1_0_Grain2", + "Body_Arch1_1", + "Body_Arch1_1_Grain0", + "Body_Arch1_1_Grain1", + "Body_Arch1_1_Grain2", + "Body_Arch1_2", + "Body_Arch1_2_Grain0", + "Body_Arch1_2_Grain1", + "Body_Arch1_2_Grain2", + "Body_Arch_1_0", + "Body_Arch_1_0_Grain0", + "Body_Arch_1_0_Grain1", + "Body_Arch_1_0_Grain2", + "Body_Arch_1_1", + "Body_Arch_1_1_Grain0", + "Body_Arch_1_1_Grain1", + "Body_Arch_1_1_Grain2", + "Body_Arch_1_2", + "Body_Arch_1_2_Grain0", + "Body_Arch_1_2_Grain1", + "Body_Arch_1_2_Grain2", + "Body_Blossom0_Petal0", + "Body_Blossom0_Petal1", + "Body_Blossom0_Petal2", + "Body_Blossom0_Petal3", + "Body_Blossom0_Petal4", + "Body_Blossom0_Pollen", + "Body_Blossom1_Petal0", + "Body_Blossom1_Petal1", + "Body_Blossom1_Petal2", + "Body_Blossom1_Petal3", + "Body_Blossom1_Petal4", + "Body_Blossom1_Pollen", + "Body_Blossom2_Petal0", + "Body_Blossom2_Petal1", + "Body_Blossom2_Petal2", + "Body_Blossom2_Petal3", + "Body_Blossom2_Petal4", + "Body_Blossom2_Pollen", + "Body_Blossom3_Petal0", + "Body_Blossom3_Petal1", + "Body_Blossom3_Petal2", + "Body_Blossom3_Petal3", + "Body_Blossom3_Petal4", + "Body_Blossom3_Pollen", + "Body_Blossom4_Petal0", + "Body_Blossom4_Petal1", + "Body_Blossom4_Petal2", + "Body_Blossom4_Petal3", + "Body_Blossom4_Petal4", + "Body_Blossom4_Pollen", + "Body_Blossom5_Petal0", + "Body_Blossom5_Petal1", + "Body_Blossom5_Petal2", + "Body_Blossom5_Petal3", + "Body_Blossom5_Petal4", + "Body_Blossom5_Pollen", + "Head_Canopy0", + "Head_Canopy0_Midrib", + "Head_Canopy0_Vein0_1", + "Head_Canopy0_Vein0__1", + "Head_Canopy0_Vein1_1", + "Head_Canopy0_Vein1__1", + "Head_Canopy0_Vein2_1", + "Head_Canopy0_Vein2__1", + "Head_Canopy1", + "Head_Canopy10", + "Head_Canopy10_Midrib", + "Head_Canopy10_Vein0_1", + "Head_Canopy10_Vein0__1", + "Head_Canopy10_Vein1_1", + "Head_Canopy10_Vein1__1", + "Head_Canopy10_Vein2_1", + "Head_Canopy10_Vein2__1", + "Head_Canopy11", + "Head_Canopy11_Midrib", + "Head_Canopy11_Vein0_1", + "Head_Canopy11_Vein0__1", + "Head_Canopy11_Vein1_1", + "Head_Canopy11_Vein1__1", + "Head_Canopy11_Vein2_1", + "Head_Canopy11_Vein2__1", + "Head_Canopy12", + "Head_Canopy12_Midrib", + "Head_Canopy12_Vein0_1", + "Head_Canopy12_Vein0__1", + "Head_Canopy12_Vein1_1", + "Head_Canopy12_Vein1__1", + "Head_Canopy12_Vein2_1", + "Head_Canopy12_Vein2__1", + "Head_Canopy13", + "Head_Canopy13_Midrib", + "Head_Canopy13_Vein0_1", + "Head_Canopy13_Vein0__1", + "Head_Canopy13_Vein1_1", + "Head_Canopy13_Vein1__1", + "Head_Canopy13_Vein2_1", + "Head_Canopy13_Vein2__1", + "Head_Canopy14", + "Head_Canopy14_Midrib", + "Head_Canopy14_Vein0_1", + "Head_Canopy14_Vein0__1", + "Head_Canopy14_Vein1_1", + "Head_Canopy14_Vein1__1", + "Head_Canopy14_Vein2_1", + "Head_Canopy14_Vein2__1", + "Head_Canopy15", + "Head_Canopy15_Midrib", + "Head_Canopy15_Vein0_1", + "Head_Canopy15_Vein0__1", + "Head_Canopy15_Vein1_1", + "Head_Canopy15_Vein1__1", + "Head_Canopy15_Vein2_1", + "Head_Canopy15_Vein2__1", + "Head_Canopy16", + "Head_Canopy16_Midrib", + "Head_Canopy16_Vein0_1", + "Head_Canopy16_Vein0__1", + "Head_Canopy16_Vein1_1", + "Head_Canopy16_Vein1__1", + "Head_Canopy16_Vein2_1", + "Head_Canopy16_Vein2__1", + "Head_Canopy17", + "Head_Canopy17_Midrib", + "Head_Canopy17_Vein0_1", + "Head_Canopy17_Vein0__1", + "Head_Canopy17_Vein1_1", + "Head_Canopy17_Vein1__1", + "Head_Canopy17_Vein2_1", + "Head_Canopy17_Vein2__1", + "Head_Canopy18", + "Head_Canopy18_Midrib", + "Head_Canopy18_Vein0_1", + "Head_Canopy18_Vein0__1", + "Head_Canopy18_Vein1_1", + "Head_Canopy18_Vein1__1", + "Head_Canopy18_Vein2_1", + "Head_Canopy18_Vein2__1", + "Head_Canopy19", + "Head_Canopy19_Midrib", + "Head_Canopy19_Vein0_1", + "Head_Canopy19_Vein0__1", + "Head_Canopy19_Vein1_1", + "Head_Canopy19_Vein1__1", + "Head_Canopy19_Vein2_1", + "Head_Canopy19_Vein2__1", + "Head_Canopy1_Midrib", + "Head_Canopy1_Vein0_1", + "Head_Canopy1_Vein0__1", + "Head_Canopy1_Vein1_1", + "Head_Canopy1_Vein1__1", + "Head_Canopy1_Vein2_1", + "Head_Canopy1_Vein2__1", + "Head_Canopy2", + "Head_Canopy20", + "Head_Canopy20_Midrib", + "Head_Canopy20_Vein0_1", + "Head_Canopy20_Vein0__1", + "Head_Canopy20_Vein1_1", + "Head_Canopy20_Vein1__1", + "Head_Canopy20_Vein2_1", + "Head_Canopy20_Vein2__1", + "Head_Canopy21", + "Head_Canopy21_Midrib", + "Head_Canopy21_Vein0_1", + "Head_Canopy21_Vein0__1", + "Head_Canopy21_Vein1_1", + "Head_Canopy21_Vein1__1", + "Head_Canopy21_Vein2_1", + "Head_Canopy21_Vein2__1", + "Head_Canopy22", + "Head_Canopy22_Midrib", + "Head_Canopy22_Vein0_1", + "Head_Canopy22_Vein0__1", + "Head_Canopy22_Vein1_1", + "Head_Canopy22_Vein1__1", + "Head_Canopy22_Vein2_1", + "Head_Canopy22_Vein2__1", + "Head_Canopy23", + "Head_Canopy23_Midrib", + "Head_Canopy23_Vein0_1", + "Head_Canopy23_Vein0__1", + "Head_Canopy23_Vein1_1", + "Head_Canopy23_Vein1__1", + "Head_Canopy23_Vein2_1", + "Head_Canopy23_Vein2__1", + "Head_Canopy2_Midrib", + "Head_Canopy2_Vein0_1", + "Head_Canopy2_Vein0__1", + "Head_Canopy2_Vein1_1", + "Head_Canopy2_Vein1__1", + "Head_Canopy2_Vein2_1", + "Head_Canopy2_Vein2__1", + "Head_Canopy3", + "Head_Canopy3_Midrib", + "Head_Canopy3_Vein0_1", + "Head_Canopy3_Vein0__1", + "Head_Canopy3_Vein1_1", + "Head_Canopy3_Vein1__1", + "Head_Canopy3_Vein2_1", + "Head_Canopy3_Vein2__1", + "Head_Canopy4", + "Head_Canopy4_Midrib", + "Head_Canopy4_Vein0_1", + "Head_Canopy4_Vein0__1", + "Head_Canopy4_Vein1_1", + "Head_Canopy4_Vein1__1", + "Head_Canopy4_Vein2_1", + "Head_Canopy4_Vein2__1", + "Head_Canopy5", + "Head_Canopy5_Midrib", + "Head_Canopy5_Vein0_1", + "Head_Canopy5_Vein0__1", + "Head_Canopy5_Vein1_1", + "Head_Canopy5_Vein1__1", + "Head_Canopy5_Vein2_1", + "Head_Canopy5_Vein2__1", + "Head_Canopy6", + "Head_Canopy6_Midrib", + "Head_Canopy6_Vein0_1", + "Head_Canopy6_Vein0__1", + "Head_Canopy6_Vein1_1", + "Head_Canopy6_Vein1__1", + "Head_Canopy6_Vein2_1", + "Head_Canopy6_Vein2__1", + "Head_Canopy7", + "Head_Canopy7_Midrib", + "Head_Canopy7_Vein0_1", + "Head_Canopy7_Vein0__1", + "Head_Canopy7_Vein1_1", + "Head_Canopy7_Vein1__1", + "Head_Canopy7_Vein2_1", + "Head_Canopy7_Vein2__1", + "Head_Canopy8", + "Head_Canopy8_Midrib", + "Head_Canopy8_Vein0_1", + "Head_Canopy8_Vein0__1", + "Head_Canopy8_Vein1_1", + "Head_Canopy8_Vein1__1", + "Head_Canopy8_Vein2_1", + "Head_Canopy8_Vein2__1", + "Head_Canopy9", + "Head_Canopy9_Midrib", + "Head_Canopy9_Vein0_1", + "Head_Canopy9_Vein0__1", + "Head_Canopy9_Vein1_1", + "Head_Canopy9_Vein1__1", + "Head_Canopy9_Vein2_1", + "Head_Canopy9_Vein2__1", + "LegL1_Moss", + "LegL1_Root", + "LegL1_Root_Grain0", + "LegL1_Root_Grain1", + "LegL1_Root_Grain2", + "LegL1_Root_Grain3", + "LegL1_Root_Grain4", + "LegL1_Sprout", + "LegL1_Sprout_Midrib", + "LegL1_Sprout_Vein0_1", + "LegL1_Sprout_Vein0__1", + "LegL1_Sprout_Vein1_1", + "LegL1_Sprout_Vein1__1", + "LegL1_Sprout_Vein2_1", + "LegL1_Sprout_Vein2__1", + "LegL1_Toe0", + "LegL1_Toe1", + "LegL1_Toe2", + "LegL_Moss", + "LegL_Root", + "LegL_Root_Grain0", + "LegL_Root_Grain1", + "LegL_Root_Grain2", + "LegL_Root_Grain3", + "LegL_Root_Grain4", + "LegL_Sprout", + "LegL_Sprout_Midrib", + "LegL_Sprout_Vein0_1", + "LegL_Sprout_Vein0__1", + "LegL_Sprout_Vein1_1", + "LegL_Sprout_Vein1__1", + "LegL_Sprout_Vein2_1", + "LegL_Sprout_Vein2__1", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegR1_Moss", + "LegR1_Root", + "LegR1_Root_Grain0", + "LegR1_Root_Grain1", + "LegR1_Root_Grain2", + "LegR1_Root_Grain3", + "LegR1_Root_Grain4", + "LegR1_Sprout", + "LegR1_Sprout_Midrib", + "LegR1_Sprout_Vein0_1", + "LegR1_Sprout_Vein0__1", + "LegR1_Sprout_Vein1_1", + "LegR1_Sprout_Vein1__1", + "LegR1_Sprout_Vein2_1", + "LegR1_Sprout_Vein2__1", + "LegR1_Toe0", + "LegR1_Toe1", + "LegR1_Toe2", + "LegR_Moss", + "LegR_Root", + "LegR_Root_Grain0", + "LegR_Root_Grain1", + "LegR_Root_Grain2", + "LegR_Root_Grain3", + "LegR_Root_Grain4", + "LegR_Sprout", + "LegR_Sprout_Midrib", + "LegR_Sprout_Vein0_1", + "LegR_Sprout_Vein0__1", + "LegR_Sprout_Vein1_1", + "LegR_Sprout_Vein1__1", + "LegR_Sprout_Vein2_1", + "LegR_Sprout_Vein2__1", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "Weapon_Basin_Rib0", + "Weapon_Basin_Rib1", + "Weapon_Basin_Rib2", + "Weapon_Basin_Rib3", + "Weapon_Basin_Rib4", + "Weapon_Basin_Rib5", + "Weapon_Basin_Rib6", + "Weapon_Basin_Rib7", + "Weapon_Basin_Rib8", + "Weapon_Basin_Rib9", + "Weapon_Basin_Rim", + "Weapon_Basin_Shell", + "Weapon_Ripple0", + "Weapon_Ripple1", + "Weapon_Ripple2", + "Weapon_Water" + ] + }, + { + "id": "s01", + "file": "unit_s01.glb", + "errors": [], + "warnings": [], + "triangles": 10340, + "mesh_parts": 34, + "primitives": 34, + "vertices": 8466, + "closed_meshes": 34, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_DiagonalBelt", + "Body_LeatherCuirass", + "Body_QuiverBolt0", + "Body_QuiverBolt1", + "Body_QuiverBolt2", + "Body_Scarf", + "Body_SplitCoat1", + "Body_SplitCoat_1", + "Body_TornScarf1", + "Body_TornScarf_1", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_Bolt", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_CrossbowStock", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "s02", + "file": "unit_s02.glb", + "errors": [], + "warnings": [], + "triangles": 12040, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9256, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Corner10_4", + "Weapon_Corner11_16", + "Weapon_Corner_10_4", + "Weapon_Corner_11_16", + "Weapon_ShieldBoss", + "Weapon_ShieldSpine", + "Weapon_TowerShield_Face", + "Weapon_TowerShield_Rim" + ] + }, + { + "id": "s03", + "file": "unit_s03.glb", + "errors": [], + "warnings": [], + "triangles": 7832, + "mesh_parts": 19, + "primitives": 19, + "vertices": 6089, + "closed_meshes": 19, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_CreamStole1", + "Body_CreamStole_1", + "Body_LongRobe", + "Body_RaggedCloak1", + "Body_RaggedCloak_1", + "Body_Scarf", + "Head_Eye1", + "Head_Eye_1", + "Head_HoodBack", + "Head_HoodRim", + "Head_Visor", + "Head_VisorSlit", + "Weapon_Trumpet" + ] + }, + { + "id": "s04", + "file": "unit_s04.glb", + "errors": [], + "warnings": [], + "triangles": 10458, + "mesh_parts": 35, + "primitives": 35, + "vertices": 8062, + "closed_meshes": 35, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Pauldron", + "ArmL_PauldronCap", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Pauldron", + "ArmR_PauldronCap", + "ArmR_Upper", + "Body_Armor_Face", + "Body_Armor_Rim", + "Body_Belt", + "Body_Tabard", + "Head_Crest", + "Head_Eye1", + "Head_Eye_1", + "Head_HelmetBack", + "Head_Visor", + "Head_VisorSlit", + "LegL_Boot", + "LegL_KneePlate", + "LegL_Shin", + "LegL_Strap", + "LegL_Thigh", + "LegR_Boot", + "LegR_KneePlate", + "LegR_Shin", + "LegR_Strap", + "LegR_Thigh", + "Weapon_Haft", + "Weapon_Head", + "Weapon_TriangleInset", + "Weapon_TriangleRim", + "Weapon_Wedge" + ] + }, + { + "id": "s05", + "file": "unit_s05.glb", + "errors": [], + "warnings": [], + "triangles": 10440, + "mesh_parts": 31, + "primitives": 31, + "vertices": 8279, + "closed_meshes": 31, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Claw0", + "ArmL_Claw1", + "ArmL_Claw2", + "ArmL_Glove", + "ArmL_Lower", + "ArmL_Upper", + "ArmR_Glove", + "ArmR_Lower", + "ArmR_Upper", + "Body_HipRag1", + "Body_HipRag_1", + "Body_HollowRib1", + "Body_HollowRib_1", + "Body_RiftEdge1", + "Body_RiftEdge_1", + "Body_TornCloth1", + "Body_TornCloth_1", + "Head_Antler1", + "Head_Antler_1", + "Head_FacelessHelm", + "Head_InnerHorn1", + "Head_InnerHorn_1", + "Head_MintCrack", + "LegL_Boot", + "LegL_Shin", + "LegL_Thigh", + "LegR_Boot", + "LegR_Shin", + "LegR_Thigh", + "Weapon_RiftLight", + "Weapon_RiftOrb" + ] + }, + { + "id": "worker", + "file": "worker.glb", + "errors": [], + "warnings": [], + "triangles": 20088, + "mesh_parts": 65, + "primitives": 65, + "vertices": 13285, + "closed_meshes": 65, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0", + "ArmL_Finger1", + "ArmL_Finger2", + "ArmL_Forearm", + "ArmL_Glove", + "ArmL_Upper", + "ArmR_Elbow", + "ArmR_Finger0", + "ArmR_Finger1", + "ArmR_Finger2", + "ArmR_Forearm", + "ArmR_Glove", + "ArmR_Upper", + "Body_ApronRivet0", + "Body_ApronRivet1", + "Body_ApronRivet2", + "Body_ApronRivet3", + "Body_ApronRivet4", + "Body_ApronRivet5", + "Body_ApronRivet6", + "Body_ClayTorso", + "Body_Harness1", + "Body_Harness_1", + "Body_LeatherApron", + "Body_Reservoir", + "Body_TankBrace0", + "Body_TankBrace1", + "Body_TankBrace2", + "Body_TankBrace3", + "Body_TankBrace4", + "Body_TankBrace5", + "Body_TankBrace6", + "Body_TankBrace7", + "Body_TankRim0_45", + "Body_TankRim0_79", + "Body_ToolPocket", + "Head_Cap", + "Head_FaceRecess", + "Head_GoggleGlint1", + "Head_GoggleGlint_1", + "Head_GoggleLens1", + "Head_GoggleLens_1", + "Head_GoggleSocket1", + "Head_GoggleSocket_1", + "Head_Hood", + "Head_Lamp", + "Head_LampHousing", + "LegL_Boot", + "LegL_Cuff", + "LegL_Shin", + "LegL_Sole", + "LegL_ToeRidge0", + "LegL_ToeRidge1", + "LegL_ToeRidge2", + "LegR_Boot", + "LegR_Cuff", + "LegR_Shin", + "LegR_Sole", + "LegR_ToeRidge0", + "LegR_ToeRidge1", + "LegR_ToeRidge2", + "WeaponL_Fork", + "WeaponL_Handle", + "WeaponR_Probe" + ] + }, + { + "id": "map_lane_segment", + "file": "map_lane_segment.glb", + "errors": [], + "warnings": [], + "triangles": 10700, + "mesh_parts": 45, + "primitives": 45, + "vertices": 8523, + "closed_meshes": 45, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Anchor_Deck", + "Anchor_JoinNorth", + "Anchor_JoinSouth", + "Body_EdgeCap1_0", + "Body_EdgeCap1_1", + "Body_EdgeCap1_2", + "Body_EdgeCap1_3", + "Body_EdgeCap_1_0", + "Body_EdgeCap_1_1", + "Body_EdgeCap_1_2", + "Body_EdgeCap_1_3", + "Body_EdgeStone1_0", + "Body_EdgeStone1_1", + "Body_EdgeStone1_2", + "Body_EdgeStone1_3", + "Body_EdgeStone_1_0", + "Body_EdgeStone_1_1", + "Body_EdgeStone_1_2", + "Body_EdgeStone_1_3", + "Body_LBasalt_00", + "Body_LBasalt_01", + "Body_LBasalt_02", + "Body_LBrassMarker_00", + "Body_LBrassMarker_01", + "Body_LMoss", + "Body_LRetainingLip", + "Body_LaneFoundation", + "Body_LaneSlab_00", + "Body_LaneSlab_01", + "Body_LaneSlab_02", + "Body_LaneSlab_03", + "Body_LaneSlab_04", + "Body_LaneSlab_05", + "Body_LightGlass1_0", + "Body_LightGlass1_1", + "Body_LightGlass_1_0", + "Body_LightGlass_1_1", + "Body_LightRecess1_0", + "Body_LightRecess1_1", + "Body_LightRecess_1_0", + "Body_LightRecess_1_1", + "Body_RBasalt_00", + "Body_RBasalt_01", + "Body_RBasalt_02", + "Body_RBrassMarker_00", + "Body_RBrassMarker_01", + "Body_RMoss", + "Body_RRetainingLip" + ] + }, + { + "id": "core_team0", + "file": "core_team0.glb", + "errors": [], + "warnings": [], + "triangles": 21436, + "mesh_parts": 64, + "primitives": 64, + "vertices": 13870, + "closed_meshes": 64, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CoreStep0", + "Body_CoreStep1", + "Body_CoreStep2", + "Body_CoreStep3", + "Body_CoreStepRim0", + "Body_CoreStepRim1", + "Body_CoreStepRim2", + "Body_CoreStepRim3", + "Body_Cradle0", + "Body_Cradle1", + "Body_Cradle2", + "Body_Cradle3", + "Body_Cradle4", + "Body_Cradle5", + "Body_CradleCollar0", + "Body_CradleCollar1", + "Body_CradleCollar2", + "Body_CradleCollar3", + "Body_CradleCollar4", + "Body_CradleCollar5", + "Body_CrystalHalo", + "Body_PlinthBlock0", + "Body_PlinthBlock1", + "Body_PlinthBlock10", + "Body_PlinthBlock11", + "Body_PlinthBlock2", + "Body_PlinthBlock3", + "Body_PlinthBlock4", + "Body_PlinthBlock5", + "Body_PlinthBlock6", + "Body_PlinthBlock7", + "Body_PlinthBlock8", + "Body_PlinthBlock9", + "Body_RadialInlay0", + "Body_RadialInlay1", + "Body_RadialInlay10", + "Body_RadialInlay11", + "Body_RadialInlay2", + "Body_RadialInlay3", + "Body_RadialInlay4", + "Body_RadialInlay5", + "Body_RadialInlay6", + "Body_RadialInlay7", + "Body_RadialInlay8", + "Body_RadialInlay9", + "Body_Seal0", + "Body_Seal1", + "Body_Seal10", + "Body_Seal11", + "Body_Seal2", + "Body_Seal3", + "Body_Seal4", + "Body_Seal5", + "Body_Seal6", + "Body_Seal7", + "Body_Seal8", + "Body_Seal9", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Team_Circle" + ] + }, + { + "id": "core_team1", + "file": "core_team1.glb", + "errors": [], + "warnings": [], + "triangles": 21632, + "mesh_parts": 66, + "primitives": 66, + "vertices": 14037, + "closed_meshes": 66, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CoreStep0", + "Body_CoreStep1", + "Body_CoreStep2", + "Body_CoreStep3", + "Body_CoreStepRim0", + "Body_CoreStepRim1", + "Body_CoreStepRim2", + "Body_CoreStepRim3", + "Body_Cradle0", + "Body_Cradle1", + "Body_Cradle2", + "Body_Cradle3", + "Body_Cradle4", + "Body_Cradle5", + "Body_CradleCollar0", + "Body_CradleCollar1", + "Body_CradleCollar2", + "Body_CradleCollar3", + "Body_CradleCollar4", + "Body_CradleCollar5", + "Body_CrystalHalo", + "Body_PlinthBlock0", + "Body_PlinthBlock1", + "Body_PlinthBlock10", + "Body_PlinthBlock11", + "Body_PlinthBlock2", + "Body_PlinthBlock3", + "Body_PlinthBlock4", + "Body_PlinthBlock5", + "Body_PlinthBlock6", + "Body_PlinthBlock7", + "Body_PlinthBlock8", + "Body_PlinthBlock9", + "Body_RadialInlay0", + "Body_RadialInlay1", + "Body_RadialInlay10", + "Body_RadialInlay11", + "Body_RadialInlay2", + "Body_RadialInlay3", + "Body_RadialInlay4", + "Body_RadialInlay5", + "Body_RadialInlay6", + "Body_RadialInlay7", + "Body_RadialInlay8", + "Body_RadialInlay9", + "Body_Seal0", + "Body_Seal1", + "Body_Seal10", + "Body_Seal11", + "Body_Seal2", + "Body_Seal3", + "Body_Seal4", + "Body_Seal5", + "Body_Seal6", + "Body_Seal7", + "Body_Seal8", + "Body_Seal9", + "Core_CrystalMain", + "Core_CrystalSatellite0", + "Core_CrystalSatellite1", + "Core_CrystalSatellite2", + "Core_CrystalSatellite3", + "Core_CrystalSatellite4", + "Team_Triangle0", + "Team_Triangle1", + "Team_Triangle2" + ] + }, + { + "id": "e01", + "file": "enemy_e01.glb", + "errors": [], + "warnings": [], + "triangles": 11984, + "mesh_parts": 38, + "primitives": 38, + "vertices": 9859, + "closed_meshes": 38, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e02", + "file": "enemy_e02.glb", + "errors": [], + "warnings": [], + "triangles": 12936, + "mesh_parts": 42, + "primitives": 42, + "vertices": 10343, + "closed_meshes": 42, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_Carapace0", + "Body_Carapace1", + "Body_Carapace2", + "Body_Carapace3", + "Body_Core", + "Body_SeamGlow0", + "Body_SeamGlow1", + "Body_SeamGlow2", + "Body_SeamGlow3", + "Body_Spine0", + "Body_Spine1", + "Body_Spine2", + "Body_Spine3", + "Head_EyeL", + "Head_EyeR", + "Head_MandibleL", + "Head_MandibleR", + "Head_Skull", + "LegL0_Inset", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_Inset", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Upper", + "LegL2_Inset", + "LegL2_Joint", + "LegL2_Shin", + "LegL2_Upper", + "LegR0_Inset", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_Inset", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Upper", + "LegR2_Inset", + "LegR2_Joint", + "LegR2_Shin", + "LegR2_Upper" + ] + }, + { + "id": "e03", + "file": "enemy_e03.glb", + "errors": [], + "warnings": [], + "triangles": 22774, + "mesh_parts": 69, + "primitives": 69, + "vertices": 17771, + "closed_meshes": 69, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_RiftHalo", + "Body_Shroud0", + "Body_Shroud1", + "Body_Shroud2", + "Body_Shroud3", + "Body_Shroud4", + "Body_Shroud5", + "Body_Shroud6", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull" + ] + }, + { + "id": "e04", + "file": "enemy_e04.glb", + "errors": [], + "warnings": [], + "triangles": 36000, + "mesh_parts": 110, + "primitives": 110, + "vertices": 27851, + "closed_meshes": 110, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibL4", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_RibR4", + "Body_Torso", + "Head_EyeL", + "Head_EyeR", + "Head_Face", + "Head_Skull", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ShinEmber", + "LegL_ShinGold", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ShinEmber", + "LegR_ShinGold", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2", + "Weapon_Arrow", + "Weapon_Bow1", + "Weapon_Bow_1", + "Weapon_String1", + "Weapon_String_1" + ] + }, + { + "id": "e05", + "file": "enemy_e05.glb", + "errors": [], + "warnings": [], + "triangles": 41846, + "mesh_parts": 125, + "primitives": 125, + "vertices": 32194, + "closed_meshes": 125, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Cuff", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Knuckle0", + "ArmL_Knuckle1", + "ArmL_Knuckle2", + "ArmL_Palm", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_StoneHammer", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Cuff", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Knuckle0", + "ArmR_Knuckle1", + "ArmR_Knuckle2", + "ArmR_Palm", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_StoneHammer", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_BackSlab0", + "Body_BackSlab1", + "Body_BackSlab2", + "Body_BackSlab3", + "Body_BruteCore", + "Body_Chest0_1", + "Body_Chest0__1", + "Body_Chest1_1", + "Body_Chest1__1", + "Body_Chest2_1", + "Body_Chest2__1", + "Body_RiftCrack", + "Body_ShoulderSpikeL0", + "Body_ShoulderSpikeL1", + "Body_ShoulderSpikeL2", + "Body_ShoulderSpikeR0", + "Body_ShoulderSpikeR1", + "Body_ShoulderSpikeR2", + "Head_Mask_EyeLight1", + "Head_Mask_EyeLight_1", + "Head_Mask_EyeSocket1", + "Head_Mask_EyeSocket_1", + "Head_Mask_MouthSlit0", + "Head_Mask_MouthSlit1", + "Head_Mask_MouthSlit2", + "Head_Mask_Nose", + "Head_Mask_Porcelain", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e06", + "file": "enemy_e06.glb", + "errors": [], + "warnings": [], + "triangles": 29198, + "mesh_parts": 84, + "primitives": 84, + "vertices": 21723, + "closed_meshes": 84, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_HealingKnot0", + "Body_HealingKnot1", + "Body_HealingKnot2", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e07", + "file": "enemy_e07.glb", + "errors": [], + "warnings": [], + "triangles": 16144, + "mesh_parts": 49, + "primitives": 49, + "vertices": 13447, + "closed_meshes": 49, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_BackArmor0", + "Body_BackArmor1", + "Body_BackArmor2", + "Body_BackArmor3", + "Body_BackArmor4", + "Body_DeerCore", + "Body_RibL0", + "Body_RibL1", + "Body_RibL2", + "Body_RibL3", + "Body_RibR0", + "Body_RibR1", + "Body_RibR2", + "Body_RibR3", + "Body_Tail", + "Head_AntlerL", + "Head_AntlerProngL0", + "Head_AntlerProngL1", + "Head_AntlerProngL2", + "Head_AntlerProngR0", + "Head_AntlerProngR1", + "Head_AntlerProngR2", + "Head_AntlerR", + "Head_EyeL", + "Head_EyeR", + "Head_Muzzle", + "Head_Neck", + "Head_Nose", + "Head_Skull", + "LegL0_ClovenLine", + "LegL0_Hoof", + "LegL0_Knee", + "LegL0_Shin", + "LegL0_Upper", + "LegL1_ClovenLine", + "LegL1_Hoof", + "LegL1_Knee", + "LegL1_Shin", + "LegL1_Upper", + "LegR0_ClovenLine", + "LegR0_Hoof", + "LegR0_Knee", + "LegR0_Shin", + "LegR0_Upper", + "LegR1_ClovenLine", + "LegR1_Hoof", + "LegR1_Knee", + "LegR1_Shin", + "LegR1_Upper" + ] + }, + { + "id": "e08", + "file": "enemy_e08.glb", + "errors": [], + "warnings": [], + "triangles": 61816, + "mesh_parts": 222, + "primitives": 222, + "vertices": 46057, + "closed_meshes": 222, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Bastion_LowerCornice", + "ArmL_Bastion_Merlon0", + "ArmL_Bastion_Merlon1", + "ArmL_Bastion_Merlon2", + "ArmL_Bastion_Merlon3", + "ArmL_Bastion_MerlonCap0", + "ArmL_Bastion_MerlonCap1", + "ArmL_Bastion_MerlonCap2", + "ArmL_Bastion_MerlonCap3", + "ArmL_Bastion_StoneKeep", + "ArmL_Bastion_UpperCornice", + "ArmL_Bastion_WindowFire0", + "ArmL_Bastion_WindowFire1", + "ArmL_Bastion_WindowFire2", + "ArmL_Bastion_WindowLintel0", + "ArmL_Bastion_WindowLintel1", + "ArmL_Bastion_WindowLintel2", + "ArmL_Bastion_WindowRecess0", + "ArmL_Bastion_WindowRecess1", + "ArmL_Bastion_WindowRecess2", + "ArmL_Castle_LowerCornice", + "ArmL_Castle_Merlon0", + "ArmL_Castle_Merlon1", + "ArmL_Castle_Merlon2", + "ArmL_Castle_Merlon3", + "ArmL_Castle_MerlonCap0", + "ArmL_Castle_MerlonCap1", + "ArmL_Castle_MerlonCap2", + "ArmL_Castle_MerlonCap3", + "ArmL_Castle_StoneKeep", + "ArmL_Castle_UpperCornice", + "ArmL_Castle_WindowFire0", + "ArmL_Castle_WindowFire1", + "ArmL_Castle_WindowFire2", + "ArmL_Castle_WindowLintel0", + "ArmL_Castle_WindowLintel1", + "ArmL_Castle_WindowLintel2", + "ArmL_Castle_WindowRecess0", + "ArmL_Castle_WindowRecess1", + "ArmL_Castle_WindowRecess2", + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_PauldronStone", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Bastion_LowerCornice", + "ArmR_Bastion_Merlon0", + "ArmR_Bastion_Merlon1", + "ArmR_Bastion_Merlon2", + "ArmR_Bastion_Merlon3", + "ArmR_Bastion_MerlonCap0", + "ArmR_Bastion_MerlonCap1", + "ArmR_Bastion_MerlonCap2", + "ArmR_Bastion_MerlonCap3", + "ArmR_Bastion_StoneKeep", + "ArmR_Bastion_UpperCornice", + "ArmR_Bastion_WindowFire0", + "ArmR_Bastion_WindowFire1", + "ArmR_Bastion_WindowFire2", + "ArmR_Bastion_WindowLintel0", + "ArmR_Bastion_WindowLintel1", + "ArmR_Bastion_WindowLintel2", + "ArmR_Bastion_WindowRecess0", + "ArmR_Bastion_WindowRecess1", + "ArmR_Bastion_WindowRecess2", + "ArmR_Castle_LowerCornice", + "ArmR_Castle_Merlon0", + "ArmR_Castle_Merlon1", + "ArmR_Castle_Merlon2", + "ArmR_Castle_Merlon3", + "ArmR_Castle_MerlonCap0", + "ArmR_Castle_MerlonCap1", + "ArmR_Castle_MerlonCap2", + "ArmR_Castle_MerlonCap3", + "ArmR_Castle_StoneKeep", + "ArmR_Castle_UpperCornice", + "ArmR_Castle_WindowFire0", + "ArmR_Castle_WindowFire1", + "ArmR_Castle_WindowFire2", + "ArmR_Castle_WindowLintel0", + "ArmR_Castle_WindowLintel1", + "ArmR_Castle_WindowLintel2", + "ArmR_Castle_WindowRecess0", + "ArmR_Castle_WindowRecess1", + "ArmR_Castle_WindowRecess2", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_PauldronStone", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_ArmoredCore", + "Body_BorderL", + "Body_BorderR", + "Body_BottomGold", + "Body_CenterGold1", + "Body_CenterGold_1", + "Body_ChestL", + "Body_ChestR", + "Body_ChestReliefL0", + "Body_ChestReliefL1", + "Body_ChestReliefL2", + "Body_ChestReliefR0", + "Body_ChestReliefR1", + "Body_ChestReliefR2", + "Body_LFastener0_59_Head", + "Body_LFastener0_59_Seat", + "Body_LFastener1_19_Head", + "Body_LFastener1_19_Seat", + "Body_RFastener0_59_Head", + "Body_RFastener0_59_Seat", + "Body_RFastener1_19_Head", + "Body_RFastener1_19_Seat", + "Body_RiftHorn1", + "Body_RiftHorn_1", + "Body_SeamL", + "Body_SeamR", + "Body_SpineGold", + "Head_Crown_LowerCornice", + "Head_Crown_Merlon0", + "Head_Crown_Merlon1", + "Head_Crown_Merlon2", + "Head_Crown_Merlon3", + "Head_Crown_MerlonCap0", + "Head_Crown_MerlonCap1", + "Head_Crown_MerlonCap2", + "Head_Crown_MerlonCap3", + "Head_Crown_StoneKeep", + "Head_Crown_UpperCornice", + "Head_Crown_WindowFire0", + "Head_Crown_WindowFire1", + "Head_Crown_WindowFire2", + "Head_Crown_WindowLintel0", + "Head_Crown_WindowLintel1", + "Head_Crown_WindowLintel2", + "Head_Crown_WindowRecess0", + "Head_Crown_WindowRecess1", + "Head_Crown_WindowRecess2", + "Head_Fire", + "Head_FireHeart", + "Head_FurnaceRecess", + "LegL_AnkleCuff", + "LegL_AnklePin", + "LegL_AnklePivot", + "LegL_AnkleRim", + "LegL_HipPin", + "LegL_HipPivot", + "LegL_HipRim", + "LegL_InnerShin", + "LegL_InnerThigh", + "LegL_KneeGuard", + "LegL_KneePin", + "LegL_KneePivot", + "LegL_KneeRim", + "LegL_ShinArmor", + "LegL_ThighArmor", + "LegL_Toe0", + "LegL_Toe1", + "LegL_Toe2", + "LegL_ToeCap0", + "LegL_ToeCap1", + "LegL_ToeCap2", + "LegR_AnkleCuff", + "LegR_AnklePin", + "LegR_AnklePivot", + "LegR_AnkleRim", + "LegR_HipPin", + "LegR_HipPivot", + "LegR_HipRim", + "LegR_InnerShin", + "LegR_InnerThigh", + "LegR_KneeGuard", + "LegR_KneePin", + "LegR_KneePivot", + "LegR_KneeRim", + "LegR_ShinArmor", + "LegR_ThighArmor", + "LegR_Toe0", + "LegR_Toe1", + "LegR_Toe2", + "LegR_ToeCap0", + "LegR_ToeCap1", + "LegR_ToeCap2" + ] + }, + { + "id": "e09", + "file": "enemy_e09.glb", + "errors": [], + "warnings": [], + "triangles": 38172, + "mesh_parts": 135, + "primitives": 135, + "vertices": 27726, + "closed_meshes": 135, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "ArmL_Elbow", + "ArmL_Finger0_0", + "ArmL_Finger0_1", + "ArmL_Finger1_0", + "ArmL_Finger1_1", + "ArmL_Finger2_0", + "ArmL_Finger2_1", + "ArmL_Finger3_0", + "ArmL_Finger3_1", + "ArmL_ForearmArmor", + "ArmL_ForearmCore", + "ArmL_Palm", + "ArmL_Pauldron", + "ArmL_Shoulder", + "ArmL_ShoulderJoint", + "ArmL_Thumb", + "ArmL_UpperArmor", + "ArmL_UpperBand", + "ArmL_UpperBandRivet_Head", + "ArmL_UpperBandRivet_Seat", + "ArmL_UpperCore", + "ArmL_WristBand", + "ArmL_WristBandRivet_Head", + "ArmL_WristBandRivet_Seat", + "ArmR_Elbow", + "ArmR_Finger0_0", + "ArmR_Finger0_1", + "ArmR_Finger1_0", + "ArmR_Finger1_1", + "ArmR_Finger2_0", + "ArmR_Finger2_1", + "ArmR_Finger3_0", + "ArmR_Finger3_1", + "ArmR_ForearmArmor", + "ArmR_ForearmCore", + "ArmR_Palm", + "ArmR_Pauldron", + "ArmR_Shoulder", + "ArmR_ShoulderJoint", + "ArmR_Thumb", + "ArmR_UpperArmor", + "ArmR_UpperBand", + "ArmR_UpperBandRivet_Head", + "ArmR_UpperBandRivet_Seat", + "ArmR_UpperCore", + "ArmR_WristBand", + "ArmR_WristBandRivet_Head", + "ArmR_WristBandRivet_Seat", + "Body_Chains1", + "Body_Chains_1", + "Body_CourtMask0_EyeLight1", + "Body_CourtMask0_EyeLight_1", + "Body_CourtMask0_EyeSocket1", + "Body_CourtMask0_EyeSocket_1", + "Body_CourtMask0_MouthSlit0", + "Body_CourtMask0_MouthSlit1", + "Body_CourtMask0_MouthSlit2", + "Body_CourtMask0_Nose", + "Body_CourtMask0_Porcelain", + "Body_CourtMask1_EyeLight1", + "Body_CourtMask1_EyeLight_1", + "Body_CourtMask1_EyeSocket1", + "Body_CourtMask1_EyeSocket_1", + "Body_CourtMask1_MouthSlit0", + "Body_CourtMask1_MouthSlit1", + "Body_CourtMask1_MouthSlit2", + "Body_CourtMask1_Nose", + "Body_CourtMask1_Porcelain", + "Body_CourtMask2_EyeLight1", + "Body_CourtMask2_EyeLight_1", + "Body_CourtMask2_EyeSocket1", + "Body_CourtMask2_EyeSocket_1", + "Body_CourtMask2_MouthSlit0", + "Body_CourtMask2_MouthSlit1", + "Body_CourtMask2_MouthSlit2", + "Body_CourtMask2_Nose", + "Body_CourtMask2_Porcelain", + "Body_CourtMask3_EyeLight1", + "Body_CourtMask3_EyeLight_1", + "Body_CourtMask3_EyeSocket1", + "Body_CourtMask3_EyeSocket_1", + "Body_CourtMask3_MouthSlit0", + "Body_CourtMask3_MouthSlit1", + "Body_CourtMask3_MouthSlit2", + "Body_CourtMask3_Nose", + "Body_CourtMask3_Porcelain", + "Body_CourtMask4_EyeLight1", + "Body_CourtMask4_EyeLight_1", + "Body_CourtMask4_EyeSocket1", + "Body_CourtMask4_EyeSocket_1", + "Body_CourtMask4_MouthSlit0", + "Body_CourtMask4_MouthSlit1", + "Body_CourtMask4_MouthSlit2", + "Body_CourtMask4_Nose", + "Body_CourtMask4_Porcelain", + "Body_CrownSpike0", + "Body_CrownSpike1", + "Body_CrownSpike2", + "Body_CrownSpike3", + "Body_CrownSpike4", + "Body_JudgeGlow", + "Body_JudgeHalo", + "Body_KnotRing0", + "Body_KnotRing1", + "Body_KnotRing2", + "Body_KnotRing3", + "Body_RobeCore", + "Body_RobeFold0", + "Body_RobeFold1", + "Body_RobeFold2", + "Body_RobeFold3", + "Body_RobeFold4", + "Body_RobeFold5", + "Body_RobeFold6", + "Body_RobeFold7", + "Body_RobeFold8", + "Head_Face_EyeLight1", + "Head_Face_EyeLight_1", + "Head_Face_EyeSocket1", + "Head_Face_EyeSocket_1", + "Head_Face_MouthSlit0", + "Head_Face_MouthSlit1", + "Head_Face_MouthSlit2", + "Head_Face_Nose", + "Head_Face_Porcelain", + "Weapon_KnotBranch1", + "Weapon_KnotBranch_1", + "Weapon_Staff", + "Weapon_StaffCollar0", + "Weapon_StaffCollar1", + "Weapon_StaffCollar2", + "Weapon_StaffCollar3", + "Weapon_StaffCollar4", + "Weapon_StaffHeart", + "Weapon_StaffKnot" + ] + }, + { + "id": "e10", + "file": "enemy_e10.glb", + "errors": [], + "warnings": [], + "triangles": 32572, + "mesh_parts": 82, + "primitives": 82, + "vertices": 25004, + "closed_meshes": 82, + "open_meshes": [], + "inward_meshes": [], + "degenerate_triangles": 0, + "part_names": [ + "Body_CrownCore", + "Body_RidgeL0", + "Body_RidgeL1", + "Body_RidgeL2", + "Body_RidgeL3", + "Body_RidgeR0", + "Body_RidgeR1", + "Body_RidgeR2", + "Body_RidgeR3", + "Body_ShellL0", + "Body_ShellL1", + "Body_ShellL2", + "Body_ShellL3", + "Body_ShellR0", + "Body_ShellR1", + "Body_ShellR2", + "Body_ShellR3", + "Body_Tail", + "Head_Brow1", + "Head_Brow_1", + "Head_CrownBand", + "Head_CrownGem0", + "Head_CrownGem1", + "Head_CrownGem2", + "Head_CrownGem3", + "Head_CrownGem4", + "Head_CrownGem5", + "Head_CrownGem6", + "Head_CrownPoint0", + "Head_CrownPoint1", + "Head_CrownPoint2", + "Head_CrownPoint3", + "Head_CrownPoint4", + "Head_CrownPoint5", + "Head_CrownPoint6", + "Head_Eye1", + "Head_Eye_1", + "Head_MawRim", + "Head_MawVoid", + "Head_RiftThroat", + "Head_Tooth0", + "Head_Tooth1", + "Head_Tooth10", + "Head_Tooth11", + "Head_Tooth12", + "Head_Tooth13", + "Head_Tooth2", + "Head_Tooth3", + "Head_Tooth4", + "Head_Tooth5", + "Head_Tooth6", + "Head_Tooth7", + "Head_Tooth8", + "Head_Tooth9", + "LegL0_Claw0", + "LegL0_Claw1", + "LegL0_Claw2", + "LegL0_Inner", + "LegL0_Joint", + "LegL0_Shin", + "LegL0_Thigh", + "LegL1_Claw0", + "LegL1_Claw1", + "LegL1_Claw2", + "LegL1_Inner", + "LegL1_Joint", + "LegL1_Shin", + "LegL1_Thigh", + "LegR0_Claw0", + "LegR0_Claw1", + "LegR0_Claw2", + "LegR0_Inner", + "LegR0_Joint", + "LegR0_Shin", + "LegR0_Thigh", + "LegR1_Claw0", + "LegR1_Claw1", + "LegR1_Claw2", + "LegR1_Inner", + "LegR1_Joint", + "LegR1_Shin", + "LegR1_Thigh" + ] + } + ], + "upgrade_pairs": [ + { + "base": "g01", + "upgrade": "g02", + "structurally_distinct": true + }, + { + "base": "g03", + "upgrade": "g04", + "structurally_distinct": true + }, + { + "base": "g05", + "upgrade": "g06", + "structurally_distinct": true + }, + { + "base": "g07", + "upgrade": "g08", + "structurally_distinct": true + }, + { + "base": "g09", + "upgrade": "g10", + "structurally_distinct": true + }, + { + "base": "m01", + "upgrade": "m02", + "structurally_distinct": true + }, + { + "base": "m03", + "upgrade": "m04", + "structurally_distinct": true + }, + { + "base": "m05", + "upgrade": "m06", + "structurally_distinct": true + }, + { + "base": "m07", + "upgrade": "m08", + "structurally_distinct": true + }, + { + "base": "m09", + "upgrade": "m10", + "structurally_distinct": true + }, + { + "base": "n01", + "upgrade": "n02", + "structurally_distinct": true + }, + { + "base": "n03", + "upgrade": "n04", + "structurally_distinct": true + }, + { + "base": "n05", + "upgrade": "n06", + "structurally_distinct": true + }, + { + "base": "n07", + "upgrade": "n08", + "structurally_distinct": true + }, + { + "base": "n09", + "upgrade": "n10", + "structurally_distinct": true + }, + { + "base": "w01", + "upgrade": "w02", + "structurally_distinct": true + }, + { + "base": "w03", + "upgrade": "w04", + "structurally_distinct": true + }, + { + "base": "w05", + "upgrade": "w06", + "structurally_distinct": true + }, + { + "base": "w07", + "upgrade": "w08", + "structurally_distinct": true + }, + { + "base": "w09", + "upgrade": "w10", + "structurally_distinct": true + } + ], + "passed": true, + "warning_count": 0 +} diff --git a/docs/phase9-glut-verification.json b/docs/phase9-glut-verification.json new file mode 100644 index 0000000..7e8a823 --- /dev/null +++ b/docs/phase9-glut-verification.json @@ -0,0 +1,3174 @@ +{ + "checks": 206, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.3833333333332, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.1000000000002, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 2, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 16.2500000000004, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + } + ], + "gold": 15, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 19.7333333333335, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 2811, + 2811 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 17, + "leaks": [ + 5, + 5 + ], + "pending_workers": 1, + "seconds": 34.5499999999993, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2245, + 2245 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 8 + } + ], + "gold": 11, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 43.2166666666655, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 9 + } + ], + "gold": 2, + "leaks": [ + 9, + 9 + ], + "pending_workers": 0, + "seconds": 38.0666666666658, + "sends": [ + "s01", + "s01" + ], + "wave": 10, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + } + ], + "gold": 0, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 19.2000000000002, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 11, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + } + ], + "gold": 39, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 46.3499999999987, + "sends": [ + "s01", + "s01" + ], + "wave": 12, + "workers": 5 + }, + { + "core_hp": [ + 1790, + 1790 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 11 + } + ], + "gold": 9, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.2333333333331, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 13, + "workers": 6 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + } + ], + "gold": 44, + "leaks": [ + 8, + 8 + ], + "pending_workers": 1, + "seconds": 44.1166666666654, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 14, + "workers": 7 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g07", + "invested": 95, + "uid": 13 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.7499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 15, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + } + ], + "gold": 11, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 24.4333333333332, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 16, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g01", + "invested": 45, + "uid": 16 + } + ], + "gold": 16, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 50.3999999999984, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 17, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g01", + "invested": 45, + "uid": 19 + } + ], + "gold": 12, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 26.8499999999998, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 18, + "workers": 8 + }, + { + "core_hp": [ + 1386, + 1386 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + } + ], + "gold": 38, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 40.9833333333323, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 19, + "workers": 8 + }, + { + "core_hp": [ + 669, + 669 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 5 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 7 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 8 + }, + { + "cell": [ + 0, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 9 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 10 + }, + { + "cell": [ + 5, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 11 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 12 + }, + { + "cell": [ + 5, + 2 + ], + "id": "g08", + "invested": 285, + "uid": 13 + }, + { + "cell": [ + 3, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 14 + }, + { + "cell": [ + 1, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 15 + }, + { + "cell": [ + 4, + 1 + ], + "id": "g02", + "invested": 135, + "uid": 16 + }, + { + "cell": [ + 0, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 17 + }, + { + "cell": [ + 5, + 1 + ], + "id": "g10", + "invested": 255, + "uid": 18 + }, + { + "cell": [ + 2, + 3 + ], + "id": "g02", + "invested": 135, + "uid": 19 + }, + { + "cell": [ + 3, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 20 + }, + { + "cell": [ + 1, + 3 + ], + "id": "g06", + "invested": 205, + "uid": 21 + }, + { + "cell": [ + 4, + 3 + ], + "id": "g09", + "invested": 85, + "uid": 22 + }, + { + "cell": [ + 0, + 3 + ], + "id": "g05", + "invested": 65, + "uid": 23 + } + ], + "gold": 19, + "leaks": [ + 8, + 8 + ], + "pending_workers": 0, + "seconds": 58.9833333333313, + "sends": [ + "s01", + "s01", + "s01", + "s01" + ], + "wave": 20, + "workers": 8 + } + ] + }, + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + } + ], + "gold": 40, + "leaks": [ + 0, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 4, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 21.3333333333334, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 3000, + 2761 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + } + ], + "gold": 22, + "leaks": [ + 0, + 4 + ], + "pending_workers": 0, + "seconds": 32.7999999999994, + "sends": [ + "s02" + ], + "wave": 3, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2436 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + } + ], + "gold": 1, + "leaks": [ + 0, + 10 + ], + "pending_workers": 1, + "seconds": 23.6333333333333, + "sends": [ + "s01" + ], + "wave": 4, + "workers": 2 + }, + { + "core_hp": [ + 3000, + 2317 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 7, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 50.1333333333318, + "sends": [ + "s01" + ], + "wave": 5, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + } + ], + "gold": 26, + "leaks": [ + 0, + 2 + ], + "pending_workers": 0, + "seconds": 51.3833333333317, + "sends": [ + "s02" + ], + "wave": 6, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 2223 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + } + ], + "gold": 17, + "leaks": [ + 0, + 0 + ], + "pending_workers": 1, + "seconds": 27.6166666666664, + "sends": [ + "s01" + ], + "wave": 7, + "workers": 3 + }, + { + "core_hp": [ + 3000, + 1726 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + } + ], + "gold": 8, + "leaks": [ + 0, + 9 + ], + "pending_workers": 1, + "seconds": 37.7999999999991, + "sends": [ + "s02" + ], + "wave": 8, + "workers": 4 + }, + { + "core_hp": [ + 2038, + 807 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g03", + "invested": 70, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 23, + "leaks": [ + 13, + 12 + ], + "pending_workers": 1, + "seconds": 43.5499999999988, + "sends": [ + "s02", + "s01" + ], + "wave": 9, + "workers": 5 + }, + { + "core_hp": [ + 2038, + 0 + ], + "formation": [ + { + "cell": [ + 2, + 0 + ], + "id": "g04", + "invested": 220, + "uid": 1 + }, + { + "cell": [ + 2, + 2 + ], + "id": "g06", + "invested": 205, + "uid": 2 + }, + { + "cell": [ + 3, + 0 + ], + "id": "g02", + "invested": 135, + "uid": 3 + }, + { + "cell": [ + 3, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 4 + }, + { + "cell": [ + 1, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 5 + }, + { + "cell": [ + 2, + 1 + ], + "id": "g09", + "invested": 85, + "uid": 6 + }, + { + "cell": [ + 1, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 7 + }, + { + "cell": [ + 4, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 8 + }, + { + "cell": [ + 0, + 2 + ], + "id": "g05", + "invested": 65, + "uid": 9 + }, + { + "cell": [ + 4, + 0 + ], + "id": "g01", + "invested": 45, + "uid": 10 + } + ], + "gold": 37, + "leaks": [ + 0, + 15 + ], + "pending_workers": 0, + "seconds": 35.1833333333326, + "sends": [ + "s01", + "s01", + "s01" + ], + "wave": 10, + "workers": 6 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "formation": [], + "gold": 220, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers": 1 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "formation": [], + "gold": 295, + "leaks": [ + 10, + 0 + ], + "pending_workers": 0, + "seconds": 13.2833333333336, + "sends": [], + "wave": 2, + "workers": 1 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "formation": [], + "gold": 373, + "leaks": [ + 11, + 0 + ], + "pending_workers": 0, + "seconds": 19.3333333333335, + "sends": [], + "wave": 3, + "workers": 1 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "formation": [], + "gold": 454, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 18.9000000000002, + "sends": [], + "wave": 4, + "workers": 1 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "formation": [], + "gold": 538, + "leaks": [ + 8, + 0 + ], + "pending_workers": 0, + "seconds": 13.5166666666669, + "sends": [], + "wave": 5, + "workers": 1 + }, + { + "core_hp": [ + 304, + 3000 + ], + "formation": [], + "gold": 625, + "leaks": [ + 13, + 0 + ], + "pending_workers": 0, + "seconds": 16.4333333333337, + "sends": [], + "wave": 6, + "workers": 1 + }, + { + "core_hp": [ + 0, + 3000 + ], + "formation": [], + "gold": 715, + "leaks": [ + 12, + 0 + ], + "pending_workers": 0, + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/phase9-logs/acceptance.log b/docs/phase9-logs/acceptance.log new file mode 100644 index 0000000..125c914 --- /dev/null +++ b/docs/phase9-logs/acceptance.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1659 checks; 0 failures; /tmp/sw9-test/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/base-models.log b/docs/phase9-logs/base-models.log new file mode 100644 index 0000000..78a84ab --- /dev/null +++ b/docs/phase9-logs/base-models.log @@ -0,0 +1,403 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:12:00 | INFO: Starting glTF 2.0 export +20:12:00 | INFO: Extracting primitive: ArmL_Elbow_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Finger0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Finger1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Finger2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Forearm_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Glove_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmL_Upper_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Elbow_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Finger0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Finger1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Finger2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Forearm_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Glove_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: ArmR_Upper_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet3_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet4_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet5_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ApronRivet6_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ClayTorso_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_Harness1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_Harness_1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_LeatherApron_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_Reservoir_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace3_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace4_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace5_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace6_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankBrace7_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankRim0_45_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_TankRim0_79_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Body_ToolPocket_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_Cap_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_FaceRecess_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleGlint1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleGlint_1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleLens1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleLens_1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleSocket1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_GoggleSocket_1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_Hood_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_Lamp_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: Head_LampHousing_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_Boot_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_Cuff_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_Shin_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_Sole_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_ToeRidge0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_ToeRidge1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegL_ToeRidge2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_Boot_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_Cuff_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_Shin_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_Sole_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_ToeRidge0_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_ToeRidge1_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: LegR_ToeRidge2_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: WeaponL_Fork_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: WeaponL_Handle_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Extracting primitive: WeaponR_Probe_Mesh +20:12:00 | INFO: Primitives created: 1 +20:12:00 | INFO: Finished glTF 2.0 export in 0.0795137882232666 s + +EXPORTED worker: 20088 triangles, 65 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/worker.glb +20:12:01 | INFO: Starting glTF 2.0 export +20:12:01 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Finished glTF 2.0 export in 0.07373380661010742 s + +EXPORTED core_team0: 20924 triangles, 63 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team0.glb +20:12:01 | INFO: Starting glTF 2.0 export +20:12:01 | INFO: Extracting primitive: Body_CoreStep0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStep3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Cradle5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal5_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal6_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal7_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal8_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal9_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal10_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Body_Seal11_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalMain_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +20:12:01 | INFO: Primitives created: 1 +20:12:01 | INFO: Finished glTF 2.0 export in 0.08976912498474121 s + +EXPORTED core_team1: 20924 triangles, 63 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team1.glb +PHASE4_EXPORT_PASS: 3 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase9-logs/build.log b/docs/phase9-logs/build.log new file mode 100644 index 0000000..d330acc --- /dev/null +++ b/docs/phase9-logs/build.log @@ -0,0 +1,2 @@ +Linux: Saumwacht-Linux-x64-0.9.0.zip (73.6 MiB) +Windows: Saumwacht-Windows-x64-0.9.0.zip (83.0 MiB) diff --git a/docs/phase9-logs/core-models.log b/docs/phase9-logs/core-models.log new file mode 100644 index 0000000..b36043e --- /dev/null +++ b/docs/phase9-logs/core-models.log @@ -0,0 +1,277 @@ +00:00.015 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.015 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +22:46:44 | INFO: Starting glTF 2.0 export +22:46:44 | INFO: Extracting primitive: Body_CoreStep0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalMain_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Team_Circle_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Finished glTF 2.0 export in 0.08010625839233398 s + +EXPORTED core_team0: 21436 triangles, 64 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team0.glb +22:46:44 | INFO: Starting glTF 2.0 export +22:46:44 | INFO: Extracting primitive: Body_CoreStep0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStep3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Cradle5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal5_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal6_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal7_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal8_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal9_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal10_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Body_Seal11_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalMain_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Team_Triangle0_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Team_Triangle1_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Extracting primitive: Team_Triangle2_Mesh +22:46:44 | INFO: Primitives created: 1 +22:46:44 | INFO: Finished glTF 2.0 export in 0.07927584648132324 s + +EXPORTED core_team1: 21632 triangles, 66 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/core_team1.glb +PHASE4_EXPORT_PASS: 2 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase9-logs/glut-regression.log b/docs/phase9-logs/glut-regression.log new file mode 100644 index 0000000..a295006 --- /dev/null +++ b/docs/phase9-logs/glut-regression.log @@ -0,0 +1,6 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPEDITION_MATCH: Standard gegen Standard; wave 20; cores [669, 669]; outcome -1 +EXPEDITION_MATCH: Standard gegen Lernmodus; wave 10; cores [2038, 0]; outcome 0 +EXPEDITION_MATCH: Leeres Baufeld gegen Standard; wave 7; cores [0, 3000]; outcome 1 +EXPEDITION_PASS: 206 checks; 0 failures; report /tmp/sw9-glut/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-verification.json diff --git a/docs/phase9-logs/godot-models.log b/docs/phase9-logs/godot-models.log new file mode 100644 index 0000000..49ad186 --- /dev/null +++ b/docs/phase9-logs/godot-models.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: Phase 4 models 59/59; 59 entries checked, 0 errors. diff --git a/docs/phase9-logs/linux-opengl.log b/docs/phase9-logs/linux-opengl.log new file mode 100644 index 0000000..a0d98d9 --- /dev/null +++ b/docs/phase9-logs/linux-opengl.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +OpenGL API 3.3.0 NVIDIA 610.57.04 - Compatibility - Using Device: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 123 checks; 0 failures; /tmp/sw9-package-opengl/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/linux-package.log b/docs/phase9-logs/linux-package.log new file mode 100644 index 0000000..5f82fb5 --- /dev/null +++ b/docs/phase9-logs/linux-package.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1660 checks; 0 failures; /tmp/sw9-package-linux/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/linux-smoke.log b/docs/phase9-logs/linux-smoke.log new file mode 100644 index 0000000..dd3887a --- /dev/null +++ b/docs/phase9-logs/linux-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (official); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw9-package-linux-smoke/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase9-logs/linux-vulkan.log b/docs/phase9-logs/linux-vulkan.log new file mode 100644 index 0000000..8271ebc --- /dev/null +++ b/docs/phase9-logs/linux-vulkan.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 123 checks; 0 failures; /tmp/sw9-package-vulkan/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/models.log b/docs/phase9-logs/models.log new file mode 100644 index 0000000..e564745 --- /dev/null +++ b/docs/phase9-logs/models.log @@ -0,0 +1,6595 @@ +00:00.014 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.014 color_management | Using fallback mode for management +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +20:19:26 | INFO: Starting glTF 2.0 export +20:19:26 | INFO: Extracting primitive: Body_Bark0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark0_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark0_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark0_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark0_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark1_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark1_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark1_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark1_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark2_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark2_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark2_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark2_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark3_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark3_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark3_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark3_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark4_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark4_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark4_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark4_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark5_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark5_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark5_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark5_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark6_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark6_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark6_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark6_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark6_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark7_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark7_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark7_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark7_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark7_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark8_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark8_Fissure0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark8_Fissure1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark8_Fissure2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Bark8_Fissure3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Petal0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Petal1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Petal2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Petal3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Petal4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Blossom_Pollen_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_MossHeart_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf0_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf1_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf2_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_ShoulderLeaf3_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn6_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn7_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Thorn8_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark0_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark0_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark1_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark1_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark2_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark2_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark3_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark3_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark4_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark4_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark5_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_WovenBark5_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Eye1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Eye_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_EyeShadow_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout1_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Sprout_1_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Finished glTF 2.0 export in 0.16556096076965332 s + +EXPORTED w01: 29782 triangles, 166 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w01.glb +20:19:26 | INFO: Starting glTF 2.0 export +20:19:26 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawDark_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Petal0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Petal1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Petal2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Petal3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Petal4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawFlower_Pollen_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf0_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf1_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf2_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf3_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf4_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_JawLeaf5_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang6_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang7_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Fang8_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Jaw_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Lip0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Lip1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Lower_Lip2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang5_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang6_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang7_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Fang8_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Jaw_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Lip0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Lip1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: Head_Upper_Lip2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:26 | INFO: Primitives created: 1 +20:19:26 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:27 | INFO: Primitives created: 1 +20:19:27 | INFO: Finished glTF 2.0 export in 0.21547412872314453 s + +EXPORTED w02: 41540 triangles, 237 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w02.glb +20:19:28 | INFO: Starting glTF 2.0 export +20:19:28 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_0_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_0_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_0_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_0_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_1_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_1_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_1_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_1_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_2_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_2_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_2_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_2_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_3_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_3_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_3_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_3_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_4_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_4_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_4_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_4_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_5_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_5_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_5_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_5_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_5_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_6_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_6_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_6_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_6_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork0_6_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_0_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_0_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_0_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_0_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_1_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_1_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_1_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_1_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_2_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_2_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_2_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_2_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_3_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_3_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_3_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_3_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_4_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_4_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_4_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_4_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_5_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_5_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_5_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_5_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_5_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_6_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_6_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_6_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_6_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork1_6_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_0_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_0_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_0_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_0_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_1_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_1_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_1_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_1_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_2_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_2_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_2_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_2_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_3_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_3_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_3_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_3_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_4_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_4_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_4_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_4_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_5_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_5_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_5_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_5_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_5_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_6_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_6_Fissure0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_6_Fissure1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_6_Fissure2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Cork2_6_Fissure3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:28 | INFO: Primitives created: 1 +20:19:28 | INFO: Finished glTF 2.0 export in 0.31575489044189453 s + +EXPORTED w03: 50052 triangles, 380 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w03.glb +20:19:30 | INFO: Starting glTF 2.0 export +20:19:30 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid4_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid4_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Braid4_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Petal0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Petal1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Petal2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Petal3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Petal4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower0_Pollen_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Petal0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Petal1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Petal2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Petal3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Petal4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower2_Pollen_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Petal0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Petal1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Petal2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Petal3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Petal4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower3_Pollen_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Petal0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Petal1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Petal2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Petal3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Petal4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Flower4_Pollen_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_InnerMoss_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log0_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log1_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log2_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log3_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log4_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Bark_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Cut_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Growth0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Growth1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Growth2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Growth3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_Growth4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_Log5_RoughEdge9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:30 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:30 | INFO: Primitives created: 1 +20:19:31 | INFO: Finished glTF 2.0 export in 0.35648322105407715 s + +EXPORTED w04: 62376 triangles, 377 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w04.glb +20:19:31 | INFO: Starting glTF 2.0 export +20:19:31 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_Seed_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:31 | INFO: Primitives created: 1 +20:19:31 | INFO: Finished glTF 2.0 export in 0.18503928184509277 s + +EXPORTED w05: 28468 triangles, 204 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w05.glb +20:19:32 | INFO: Starting glTF 2.0 export +20:19:32 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_Seed_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:32 | INFO: Primitives created: 1 +20:19:32 | INFO: Finished glTF 2.0 export in 0.22878074645996094 s + +EXPORTED w06: 37768 triangles, 296 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w06.glb +20:19:33 | INFO: Starting glTF 2.0 export +20:19:33 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:19:33 | INFO: Primitives created: 1 +20:19:33 | INFO: Finished glTF 2.0 export in 0.31166696548461914 s + +EXPORTED w07: 46028 triangles, 366 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w07.glb +20:19:35 | INFO: Starting glTF 2.0 export +20:19:35 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk0_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk0_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk0_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk0_Grain3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk1_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk1_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk1_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk1_Grain3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk2_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk2_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk2_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_FungalTrunk2_Grain3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup0_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup1_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup2_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_SmallCup3_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe5_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe6_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe7_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe8_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe9_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe10_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Fringe11_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rib11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup0_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe5_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe6_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe7_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe8_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe9_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe10_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Fringe11_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rib11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup1_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe0_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe1_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe2_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe3_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe4_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe5_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe6_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe7_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe8_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe9_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe10_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Fringe11_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib5_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib6_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib7_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib8_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib9_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib10_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rib11_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Rim_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: Head_Cup2_Shell_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:35 | INFO: Primitives created: 1 +20:19:35 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore0_0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore0_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore0_2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore0_3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore0_4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore1_0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore1_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore1_2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore1_3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore1_4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore2_0_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore2_1_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore2_2_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore2_3_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Extracting primitive: Weapon_Spore2_4_Mesh +20:19:36 | INFO: Primitives created: 1 +20:19:36 | INFO: Finished glTF 2.0 export in 0.5987498760223389 s + +EXPORTED w08: 77860 triangles, 700 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w08.glb +20:19:37 | INFO: Starting glTF 2.0 export +20:19:37 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown0_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown1_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown2_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown3_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Head_Crown4_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_DewOrb_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Extracting primitive: Weapon_Water_Mesh +20:19:37 | INFO: Primitives created: 1 +20:19:37 | INFO: Finished glTF 2.0 export in 0.1616353988647461 s + +EXPORTED w09: 30280 triangles, 199 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w09.glb +20:19:38 | INFO: Starting glTF 2.0 export +20:19:38 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Moss_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Toe0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Toe1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL1_Toe2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Moss_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Toe0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Toe1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegL_Toe2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Moss_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Toe0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Toe1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR1_Toe2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Moss_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Toe0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Toe1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: LegR_Toe2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Extracting primitive: Weapon_Water_Mesh +20:19:38 | INFO: Primitives created: 1 +20:19:38 | INFO: Finished glTF 2.0 export in 0.29185032844543457 s + +EXPORTED w10: 40508 triangles, 348 parts -> /home/martin/Dokumente/Projekte/TowerDefense/saumwacht-godot/assets/models/unit_w10.glb +PHASE4_EXPORT_PASS: 10 models +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase9-logs/references.log b/docs/phase9-logs/references.log new file mode 100644 index 0000000..74c9581 --- /dev/null +++ b/docs/phase9-logs/references.log @@ -0,0 +1,48 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w01_dornhopser_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w02_rankenschnapper_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w01.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w03_korkruecken_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w04_ringborke_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w03.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w05_samenschleuder_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w06_zapfenkrone_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w05.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w07_sporenkelch_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w08_pilzkathedrale_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w07.png +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w09_tauhueter_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +WARNING: Loaded resource as image file, this will not work on export: 'res://assets/icons/wurzelbund/unit_w10_quellgeflecht_icon.png'. Instead, import the image file as an Image resource and load it normally as a resource. + at: load_from_file (core/io/image.cpp:2780) + GDScript backtrace (most recent call first): + [0] _ready (res://tools/model_reference_sheet.gd:56) +REFERENCE_CAPTURED res://docs/screenshots/phase4/reference-w09.png diff --git a/docs/phase9-logs/rules.log b/docs/phase9-logs/rules.log new file mode 100644 index 0000000..7bd78ac --- /dev/null +++ b/docs/phase9-logs/rules.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +PASS: 209 checks across economy, combat and the full match lifecycle. diff --git a/docs/phase9-logs/runtime.log b/docs/phase9-logs/runtime.log new file mode 100644 index 0000000..f642a55 --- /dev/null +++ b/docs/phase9-logs/runtime.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +PHASE6_RUNTIME: {"audio_events":123,"checks":9,"device":"NVIDIA GeForce RTX 5060 Ti","engine":"4.7.2-stable (fedora)","failures":[],"frames":1729,"max_draw_calls":4429,"mean_fps":144.048869641272,"mean_frame_ms":6.94208849045691,"p95_frame_ms":12.883,"renderer":"forward_plus","sample_seconds":12,"speed":2,"units_at_start":86,"viewport":"(1600.0, 960.0)","wave":20} diff --git a/docs/phase9-logs/short-regression.log b/docs/phase9-logs/short-regression.log new file mode 100644 index 0000000..b2771ce --- /dev/null +++ b/docs/phase9-logs/short-regression.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +RUNTIME_BATCHING: 6758 original parts -> 325 material surfaces across catalog assets +SLICE_MATCH: Standard gegen Lernmodus; wave 8; outcome 0; cores [3000, 1035] +SLICE_MATCH: Standard gegen Standard; wave 8; outcome -1; cores [3000, 3000] +SLICE_MATCH: Leeres Baufeld gegen Standard; wave 7; outcome 1; cores [0, 3000] +PHASE5_PASS: 403 checks; 3 real-budget matches; 0 failures diff --git a/docs/phase9-logs/smoke.log b/docs/phase9-logs/smoke.log new file mode 100644 index 0000000..cb471d9 --- /dev/null +++ b/docs/phase9-logs/smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw9-smoke/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase9-logs/standalone.log b/docs/phase9-logs/standalone.log new file mode 100644 index 0000000..9c303d6 --- /dev/null +++ b/docs/phase9-logs/standalone.log @@ -0,0 +1,2932 @@ +00:00.016 color_management | ERROR OpenColorIO Error: Error: Loading the OCIO profile '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' failed. This .ocio config '/usr/share/blender/5.2/datafiles/colormanagement/config.ocio' is version 2.5. This version of the OpenColorIO library (2.4.2) is not able to load that config version. + | The minor version 5 is not supported for major version 2. Maximum minor version is 4. +00:00.016 color_management | Using fallback mode for management +/tmp/saumwacht-standalone-fcztaji1/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +ERROR Draco is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_draco_bridge.so +ERROR MeshOptimizer is not available because library could not be found at /usr/lib/blender/5.2/scripts/addons_core/io_scene_gltf2/libbf_intern_meshopt_bridge.so +22:41:03 | INFO: Starting glTF 2.0 export +22:41:03 | INFO: Extracting primitive: ArmL0_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL0_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL0_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL0_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL1_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL1_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL1_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL1_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL2_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL2_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL2_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL2_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmL_Shoulder_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR0_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR0_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR0_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR0_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR1_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR1_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR1_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR1_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR2_Housing_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR2_Pivot_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR2_Pivot_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR2_Rod_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: ArmR_Shoulder_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Body_Breastplate_Face_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Body_Breastplate_Rim_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Body_HipPlateL_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Body_HipPlateR_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Body_Waist_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Head_Eye1_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Head_Eye_1_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Head_Face_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_AnkleGold_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Greave_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Knee_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Knee_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Piston_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Shin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_ThighArmor_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Toe0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg0_Toe1_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_AnkleGold_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Greave_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Knee_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Knee_Pin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Piston_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Shin_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_ThighArmor_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Toe0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: Leg1_Toe1_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponL0_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponL1_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponL2_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponR0_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponR1_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Extracting primitive: WeaponR2_Blade0_Mesh +22:41:03 | INFO: Primitives created: 1 +22:41:03 | INFO: Finished glTF 2.0 export in 0.05985307693481445 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_tank.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_tank.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED m04: 1398 triangles, 60 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_m04.glb +STANDALONE_PASS: m04 +22:41:06 | INFO: Starting glTF 2.0 export +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_LowerCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_Merlon0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_Merlon1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_Merlon2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_Merlon3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_MerlonCap3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_StoneKeep_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_UpperCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowFire0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowFire1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowFire2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowLintel2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Bastion_WindowRecess2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_LowerCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_Merlon0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_Merlon1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_Merlon2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_Merlon3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_MerlonCap0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_MerlonCap1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_MerlonCap2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_MerlonCap3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_StoneKeep_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_UpperCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowFire0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowFire1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowFire2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowLintel0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowLintel1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowLintel2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowRecess0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowRecess1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Castle_WindowRecess2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Elbow_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger0_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger0_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger1_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger1_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger2_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger2_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger3_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Finger3_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Palm_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_PauldronStone_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_Thumb_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_WristBand_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_LowerCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_Merlon0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_Merlon1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_Merlon2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_Merlon3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_MerlonCap3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_StoneKeep_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_UpperCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowFire0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowFire1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowFire2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowLintel2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Bastion_WindowRecess2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_LowerCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_Merlon0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_Merlon1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_Merlon2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_Merlon3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_MerlonCap0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_MerlonCap1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_MerlonCap2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_MerlonCap3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_StoneKeep_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_UpperCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowFire0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowFire1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowFire2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowLintel0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowLintel1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowLintel2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowRecess0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowRecess1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Castle_WindowRecess2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Elbow_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger0_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger0_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger1_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger1_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger2_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger2_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger3_0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Finger3_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Palm_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_PauldronStone_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_Thumb_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_WristBand_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ArmoredCore_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_BorderL_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_BorderR_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_BottomGold_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_CenterGold1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_CenterGold_1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestL_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestR_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefL0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefL1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefL2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefR0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefR1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_ChestReliefR2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_LFastener0_59_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_LFastener0_59_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_LFastener1_19_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_LFastener1_19_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_RFastener0_59_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_RFastener0_59_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_RFastener1_19_Head_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_RFastener1_19_Seat_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_SeamL_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_SeamR_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Body_SpineGold_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_LowerCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_Merlon0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_Merlon1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_Merlon2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_Merlon3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_MerlonCap0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_MerlonCap1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_MerlonCap2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_MerlonCap3_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_StoneKeep_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_UpperCornice_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowFire0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowFire1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowFire2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowLintel0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowLintel1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowLintel2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowRecess0_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowRecess1_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Crown_WindowRecess2_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_Fire_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_FireHeart_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: Head_FurnaceRecess_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: LegL_AnklePin_Mesh +22:41:06 | INFO: Primitives created: 1 +22:41:06 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_HipPin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_HipPivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_HipRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_InnerShin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_KneePin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_KneePivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_KneeRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_Toe0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_Toe1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_Toe2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_AnklePin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_HipPin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_HipPivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_HipRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_InnerShin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_KneePin_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_KneePivot_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_KneeRim_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_Toe0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_Toe1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_Toe2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Finished glTF 2.0 export in 0.2711319923400879 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_ranged.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_ranged.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED g04: 61340 triangles, 220 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_g04.glb +STANDALONE_PASS: g04 +22:41:07 | INFO: Starting glTF 2.0 export +22:41:07 | INFO: Extracting primitive: Body_Braid0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid0_Grain0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid0_Grain1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid0_Grain2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid1_Grain0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid1_Grain1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid1_Grain2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid2_Grain0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid2_Grain1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid2_Grain2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid3_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid3_Grain0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid3_Grain1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Braid3_Grain2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf1_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_BroadLeaf_1_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Petal0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Petal1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Petal2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Petal3_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Petal4_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower1_Pollen_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Petal0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Petal1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Petal2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Petal3_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Petal4_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_Flower_1_Pollen_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf0_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf1_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf2_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf3_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf4_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf5_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein0__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein1__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2_1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf6_Vein2__1_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:07 | INFO: Extracting primitive: Body_TrunkLeaf7_Midrib_Mesh +22:41:07 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TrunkLeaf7_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib5_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib6_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib7_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib8_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rib9_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Rim_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Launcher_Shell_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale0_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale1_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale2_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale3_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale4_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale5_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale6_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale7_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale8_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale9_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale10_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_LauncherScale11_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_Seed_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam5_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SeedSeam6_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Moss_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Toe0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Toe1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL1_Toe2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Moss_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Toe0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Toe1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegL_Toe2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Moss_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Toe0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Toe1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR1_Toe2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Moss_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Toe0_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Toe1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: LegR_Toe2_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Finished glTF 2.0 export in 0.2651844024658203 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_artillery.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w06: 37768 triangles, 296 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_w06.glb +STANDALONE_PASS: w06 +22:41:08 | INFO: Starting glTF 2.0 export +22:41:08 | INFO: Extracting primitive: ArmL_Sickle_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: ArmR_Sickle_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_ArchMask_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_ArchMask_Eye1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_ArchMask_Eye_1_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_BellSkirt_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_CathedralFrontArch_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_CathedralShell_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_CentralFlow_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TailL_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_TailR_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_WispL_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Body_WispR_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_CentralSpire_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SpireL_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Head_SpireR_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Weapon_Clapper_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Extracting primitive: Weapon_ClapperChain_Mesh +22:41:08 | INFO: Primitives created: 1 +22:41:08 | INFO: Finished glTF 2.0 export in 0.01853179931640625 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_support.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_support.py:1094: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat=bpy.data.materials.new(name);mat['material_name']=name;mat.use_nodes=True + +EXPORTED n08: 1482 triangles, 18 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_n08.glb +STANDALONE_PASS: n08 +22:41:09 | INFO: Starting glTF 2.0 export +22:41:09 | INFO: Extracting primitive: ArmL_BasinVine_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmL_BasinVine_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmL_BasinVine_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmL_BasinVine_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmR_BasinVine_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmR_BasinVine_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmR_BasinVine_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: ArmR_BasinVine_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_0_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_0_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_0_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_1_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_1_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_1_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_2_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_2_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch1_2_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_0_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_0_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_0_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_1_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_1_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_1_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_2_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_2_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Arch_1_2_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom0_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom1_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom2_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom3_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom4_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Petal0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Petal1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Petal2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Petal3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Petal4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Body_Blossom5_Pollen_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy0_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy1_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy2_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy3_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy4_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy5_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy6_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy7_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy8_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy9_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy10_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy11_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy12_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy13_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy14_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy15_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy16_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy17_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy18_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy19_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy20_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy21_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy22_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Head_Canopy23_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Moss_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Grain3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Root_Grain4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Sprout_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Toe0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Toe1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL1_Toe2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Moss_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Grain3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Root_Grain4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Sprout_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Toe0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Toe1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegL_Toe2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Moss_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Grain3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Root_Grain4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Sprout_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Toe0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Toe1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR1_Toe2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Moss_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Grain0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Grain1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Grain2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Grain3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Root_Grain4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Midrib_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein0_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein0__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein1_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein1__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein2_1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Sprout_Vein2__1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Toe0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Toe1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: LegR_Toe2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib3_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib4_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib5_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib6_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib7_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib8_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rib9_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Rim_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Basin_Shell_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Ripple0_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Ripple1_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Ripple2_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Extracting primitive: Weapon_Water_Mesh +22:41:09 | INFO: Primitives created: 1 +22:41:09 | INFO: Finished glTF 2.0 export in 0.2995121479034424 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_mercenary.py:234: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True + +EXPORTED w10: 40508 triangles, 348 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_w10.glb +STANDALONE_PASS: w10 +22:41:10 | INFO: Starting glTF 2.0 export +22:41:10 | INFO: Extracting primitive: ArmL_Glove_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Lower_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Pauldron_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_PauldronCap_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Upper_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Glove_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Lower_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Pauldron_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_PauldronCap_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Upper_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Armor_Face_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Armor_Rim_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Belt_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Tabard_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Crest_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Eye1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Eye_1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_HelmetBack_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Visor_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_VisorSlit_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Boot_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_KneePlate_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Shin_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Strap_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Thigh_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Boot_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_KneePlate_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Shin_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Strap_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Thigh_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Weapon_Haft_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Weapon_Head_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Weapon_TriangleInset_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Weapon_TriangleRim_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Weapon_Wedge_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Finished glTF 2.0 export in 0.04143238067626953 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_worker.py:190: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_worker.py:460: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED s04: 10458 triangles, 35 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_s04.glb +STANDALONE_PASS: s04 +22:41:10 | INFO: Starting glTF 2.0 export +22:41:10 | INFO: Extracting primitive: ArmL_Elbow_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Finger0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Finger1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Finger2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Forearm_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Glove_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmL_Upper_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Elbow_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Finger0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Finger1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Finger2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Forearm_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Glove_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: ArmR_Upper_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet3_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet4_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet5_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ApronRivet6_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ClayTorso_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Harness1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Harness_1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_LeatherApron_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_Reservoir_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace3_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace4_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace5_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace6_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankBrace7_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankRim0_45_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_TankRim0_79_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Body_ToolPocket_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Cap_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_FaceRecess_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleGlint1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleGlint_1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleLens1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleLens_1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleSocket1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_GoggleSocket_1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Hood_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_Lamp_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: Head_LampHousing_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Boot_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Cuff_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Shin_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_Sole_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_ToeRidge0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_ToeRidge1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegL_ToeRidge2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Boot_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Cuff_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Shin_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_Sole_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_ToeRidge0_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_ToeRidge1_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: LegR_ToeRidge2_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: WeaponL_Fork_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: WeaponL_Handle_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Extracting primitive: WeaponR_Probe_Mesh +22:41:10 | INFO: Primitives created: 1 +22:41:10 | INFO: Finished glTF 2.0 export in 0.07326960563659668 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_lane.py:189: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_lane.py:459: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED worker: 20088 triangles, 65 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/worker.glb +STANDALONE_PASS: worker +22:41:11 | INFO: Starting glTF 2.0 export +22:41:11 | INFO: Extracting primitive: Body_EdgeCap1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap1_2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap1_3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap_1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap_1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap_1_2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeCap_1_3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone1_2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone1_3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone_1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone_1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone_1_2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_EdgeStone_1_3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneFoundation_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_00_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_01_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_02_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_03_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_04_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LaneSlab_05_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LBasalt_00_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LBasalt_01_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LBasalt_02_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LBrassMarker_00_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LBrassMarker_01_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightGlass1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightGlass1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightGlass_1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightGlass_1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightRecess1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightRecess1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightRecess_1_0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LightRecess_1_1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LMoss_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_LRetainingLip_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RBasalt_00_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RBasalt_01_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RBasalt_02_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RBrassMarker_00_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RBrassMarker_01_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RMoss_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RRetainingLip_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Finished glTF 2.0 export in 0.0550229549407959 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_core.py:203: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_core.py:473: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_core.py:1365: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + crystal=bpy.data.materials.new('SW_HD_Core_%d'%team);crystal['material_name']=crystal.name;crystal.use_nodes=True + +EXPORTED map_lane_segment: 10700 triangles, 45 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/map_lane_segment.glb +STANDALONE_PASS: map_lane_segment +22:41:11 | INFO: Starting glTF 2.0 export +22:41:11 | INFO: Extracting primitive: Body_CoreStep0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStep1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStep2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStep3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStepRim0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStepRim1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStepRim2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CoreStepRim3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Cradle5_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CradleCollar5_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_CrystalHalo_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock5_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock6_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock7_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock8_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock9_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock10_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_PlinthBlock11_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay5_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay6_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay7_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay8_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay9_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay10_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_RadialInlay11_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal5_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal6_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal7_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal8_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal9_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal10_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Body_Seal11_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalMain_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalSatellite0_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalSatellite1_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalSatellite2_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalSatellite3_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Extracting primitive: Core_CrystalSatellite4_Mesh +22:41:11 | INFO: Primitives created: 1 +22:41:11 | INFO: Finished glTF 2.0 export in 0.0765540599822998 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED core_team1: 20924 triangles, 63 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/core_team1.glb +STANDALONE_PASS: core_team1 +STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved +22:41:13 | INFO: Starting glTF 2.0 export +22:41:13 | INFO: Extracting primitive: ArmL_Elbow_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Palm_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_Shoulder_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_UpperBand_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_UpperCore_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_WristBand_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Elbow_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Palm_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_Shoulder_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_UpperBand_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_UpperCore_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_WristBand_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_LavaCore_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell0_0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell0_1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell0_2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell0_3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell1_0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell1_1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell1_2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell1_3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell2_0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell2_1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell2_2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Body_Shell2_3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_BrowL_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_BrowR_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_CheekL_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_CheekR_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_Chin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_EyeL_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_EyeR_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_JawCavity_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothL0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothL1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothL2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothL3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothR0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothR1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothR2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_LowerToothR3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_MouthEmber_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothL0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothL1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothL2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothL3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothR0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothR1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothR2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: Head_UpperToothR3_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_AnklePin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_AnklePivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_AnkleRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_HipPin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_HipPivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_HipRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_InnerShin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_InnerThigh_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_KneeGuard_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_KneePin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_KneePivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_KneeRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_ShinArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_ThighArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_Toe0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_Toe1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_Toe2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_ToeCap0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_ToeCap1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegL_ToeCap2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_AnklePin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_AnklePivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_AnkleRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_HipPin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_HipPivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_HipRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_InnerShin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_InnerThigh_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_KneeGuard_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_KneePin_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_KneePivot_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_KneeRim_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_ShinArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_ThighArmor_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_Toe0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_Toe1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_Toe2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_ToeCap0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_ToeCap1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: LegR_ToeCap2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponL_Claw0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponL_Claw1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponL_Claw2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponR_Claw0_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponR_Claw1_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Extracting primitive: WeaponR_Claw2_Mesh +22:41:13 | INFO: Primitives created: 1 +22:41:13 | INFO: Finished glTF 2.0 export in 0.20798110961914062 s +/tmp/saumwacht-standalone-fcztaji1/scripts/create_melee.py:259: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.use_nodes = True +/tmp/saumwacht-standalone-fcztaji1/scripts/create_melee.py:529: DeprecationWarning: 'Material.use_nodes' is expected to be removed in Blender 6.0 + mat.diffuse_color=(*c,1);mat.use_nodes=True + +EXPORTED g01: 51844 triangles, 131 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_g01.glb +STANDALONE_PASS: g01 +22:41:15 | INFO: Starting glTF 2.0 export +22:41:15 | INFO: Extracting primitive: ArmL_Elbow_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_ForearmArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_ForearmCore_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle0_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle0_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle1_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle1_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle2_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Knuckle2_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Palm_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_Shoulder_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_ShoulderJoint_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_ShoulderTrim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_UpperArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_UpperBand_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_UpperBandRivet_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_UpperBandRivet_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_UpperCore_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_WristBand_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_WristBandRivet_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmL_WristBandRivet_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Elbow_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_ForearmArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_ForearmCore_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle0_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle0_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle1_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle1_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle2_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Knuckle2_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Palm_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_Shoulder_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_ShoulderJoint_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_ShoulderTrim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_UpperArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_UpperBand_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_UpperBandRivet_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_UpperBandRivet_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_UpperCore_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_WristBand_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_WristBandRivet_Head_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: ArmR_WristBandRivet_Seat_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_DorsalSpine0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_DorsalSpine1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_DorsalSpine2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_LavaCore_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell0_0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell0_1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell0_2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell0_3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell1_0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell1_1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell1_2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell1_3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell2_0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell2_1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell2_2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Body_Shell2_3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_BrowL_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_BrowR_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_CheekL_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_CheekR_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_Chin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_EyeL_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_EyeR_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_JawCavity_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothL0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothL1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothL2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothL3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothR0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothR1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothR2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_LowerToothR3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_MouthEmber_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothL0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothL1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothL2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothL3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothR0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothR1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothR2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: Head_UpperToothR3_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_AnkleCuff_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_AnklePin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_AnklePivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_AnkleRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_HipPin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_HipPivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_HipRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_InnerShin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_InnerThigh_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_KneeGuard_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_KneePin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_KneePivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_KneeRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_ShinArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_ThighArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_Toe0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_Toe1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_Toe2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_ToeCap0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_ToeCap1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegL_ToeCap2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_AnkleCuff_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_AnklePin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_AnklePivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_AnkleRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_HipPin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_HipPivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_HipRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_InnerShin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_InnerThigh_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_KneeGuard_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_KneePin_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_KneePivot_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_KneeRim_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_ShinArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_ThighArmor_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_Toe0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_Toe1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_Toe2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_ToeCap0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_ToeCap1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: LegR_ToeCap2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponL_Claw0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponL_Claw1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponL_Claw2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponR_Claw0_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponR_Claw1_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Extracting primitive: WeaponR_Claw2_Mesh.001 +22:41:15 | INFO: Primitives created: 1 +22:41:15 | INFO: Finished glTF 2.0 export in 0.1674785614013672 s +00:12.703 blend | Read blend: "/tmp/saumwacht-standalone-fcztaji1/blend/n08.blend" + +EXPORTED g01: 51844 triangles, 131 parts -> /tmp/saumwacht-standalone-fcztaji1/exports/unit_g01.glb +STANDALONE_PASS: g01 +KEEP_SCENE_PASS: two generated scenes and original scene retained +Warning: Library file, loading empty scene +NATIVE_BLEND_PASS: isolated N08 scene reopened; 20 objects +Blender 5.2.1 LTS (hash unknown built 2026-08-27 00:00:00) + +Blender quit diff --git a/docs/phase9-logs/ui-final.log b/docs/phase9-logs/ui-final.log new file mode 100644 index 0000000..6411d56 --- /dev/null +++ b/docs/phase9-logs/ui-final.log @@ -0,0 +1,3 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_PASS: 108 checks; 0 failures; /tmp/sw9-lastui2/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/visual-acceptance.log b/docs/phase9-logs/visual-acceptance.log new file mode 100644 index 0000000..fa063db --- /dev/null +++ b/docs/phase9-logs/visual-acceptance.log @@ -0,0 +1,8 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1676 checks; 0 failures; /tmp/sw9-finalvisual/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/visual-ui.log b/docs/phase9-logs/visual-ui.log new file mode 100644 index 0000000..03c9417 --- /dev/null +++ b/docs/phase9-logs/visual-ui.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org +Vulkan 1.4.341 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 5060 Ti + +FACTION_PASS: 119 checks; 0 failures; /tmp/sw9-visual/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/windows-package.log b/docs/phase9-logs/windows-package.log new file mode 100644 index 0000000..f4e4868 --- /dev/null +++ b/docs/phase9-logs/windows-package.log @@ -0,0 +1,7 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +FACTION_MATCH: Wurzelbund gegen Glutpakt wave 20 cores [1244, 1709] +FACTION_MATCH: Glutpakt gegen Wurzelbund wave 20 cores [1709, 1244] +FACTION_MATCH: Wurzelbund Spiegel wave 20 cores [1244, 1244] +FACTION_MATCH: Wurzelbund Kurzpartie wave 8 cores [3000, 3000] +FACTION_PASS: 1660 checks; 0 failures; /tmp/sw9-package-windows/data/godot/app_userdata/Saumwacht · Glutpakt/phase9-verification.json diff --git a/docs/phase9-logs/windows-smoke.log b/docs/phase9-logs/windows-smoke.log new file mode 100644 index 0000000..b9ddb58 --- /dev/null +++ b/docs/phase9-logs/windows-smoke.log @@ -0,0 +1,4 @@ +Godot Engine v4.7.2.stable.fedora.ed1daf0bf - https://godotengine.org + +EXPORT_SMOKE_PASS: 274 checks; 0 failures; engine 4.7.2-stable (fedora); cores [3000, 1035] +SMOKE_CAPTURES: /tmp/sw9-package-windows-smoke/data/godot/app_userdata/Saumwacht · Glutpakt/phase8-smoke diff --git a/docs/phase9-package-check.json b/docs/phase9-package-check.json new file mode 100644 index 0000000..a925e8a --- /dev/null +++ b/docs/phase9-package-check.json @@ -0,0 +1,28 @@ +{ + "version": "0.9.0", + "packages": [ + { + "platform": "Linux", + "crc_ok": true, + "sha256": "46ff07ef760d07e0a84aa6cc1374b2c00ba9ebd37c36684608df9f07953c40da", + "exe_sha256": "fb06e6bf989c56b74e67afe03322fddf99134a1d320325be420b7b7f09cdd735", + "archive_bytes": 77145514, + "path": "/tmp/saumwacht-phase9-release/Linux/Saumwacht-Linux/Saumwacht.x86_64" + }, + { + "platform": "Windows", + "crc_ok": true, + "sha256": "5fb7e39e7571f1f567f4082187fbbab927b134809fe8b5a4154d5a5887032418", + "exe_sha256": "d66d243f56064f1695d3f6f7b5cd274541972d34bd11480892f44455f71439fd", + "archive_bytes": 87060905, + "path": "/tmp/saumwacht-phase9-release/Windows/Saumwacht-Windows/Saumwacht.exe" + } + ], + "windows_native_test": false, + "linux_checks": 1660, + "windows_checks": 1660, + "opengl_checks": 123, + "vulkan_checks": 123, + "linux_smoke_checks": 274, + "windows_smoke_checks": 274 +} diff --git a/docs/phase9-package-linux.json b/docs/phase9-package-linux.json new file mode 100644 index 0000000..442c077 --- /dev/null +++ b/docs/phase9-package-linux.json @@ -0,0 +1,5504 @@ +{ + "checks": 1660, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase9-package-opengl.json b/docs/phase9-package-opengl.json new file mode 100644 index 0000000..dfb12b3 --- /dev/null +++ b/docs/phase9-package-opengl.json @@ -0,0 +1,7 @@ +{ + "checks": 123, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "gl_compatibility" +} \ No newline at end of file diff --git a/docs/phase9-package-vulkan.json b/docs/phase9-package-vulkan.json new file mode 100644 index 0000000..d6b3c32 --- /dev/null +++ b/docs/phase9-package-vulkan.json @@ -0,0 +1,7 @@ +{ + "checks": 123, + "engine": "4.7.2-stable (official)", + "failures": [], + "matches": [], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase9-package-windows.json b/docs/phase9-package-windows.json new file mode 100644 index 0000000..d013dc1 --- /dev/null +++ b/docs/phase9-package-windows.json @@ -0,0 +1,5504 @@ +{ + "checks": 1660, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase9-runtime.json b/docs/phase9-runtime.json new file mode 100644 index 0000000..1c94fbf --- /dev/null +++ b/docs/phase9-runtime.json @@ -0,0 +1,18 @@ +{ + "audio_events": 123, + "checks": 9, + "device": "NVIDIA GeForce RTX 5060 Ti", + "engine": "4.7.2-stable (fedora)", + "failures": [], + "frames": 1729, + "max_draw_calls": 4429, + "mean_fps": 144.048869641272, + "mean_frame_ms": 6.94208849045691, + "p95_frame_ms": 12.883, + "renderer": "forward_plus", + "sample_seconds": 12, + "speed": 2, + "units_at_start": 86, + "viewport": "(1600.0, 960.0)", + "wave": 20 +} \ No newline at end of file diff --git a/docs/phase9-short-balance.md b/docs/phase9-short-balance.md new file mode 100644 index 0000000..384c6da --- /dev/null +++ b/docs/phase9-short-balance.md @@ -0,0 +1,102 @@ +# Glutpakt · Daten und vollständige Testpartien + +Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler. + +## Einheiten + +Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit. + +| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit | +| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- | +| g01 | Kohlenbeißer | 45 | 260 | 17 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s. | +| g02 | Schlackenklaue | 90 | 690 | 44 | 1.2 | Klinge | Schwer | Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s. | +| g03 | Schlackenwacht | 70 | 650 | 11 | 1.2 | Klinge | Schwer | Erste 8 s: 15 % weniger erlittener Schaden. | +| g04 | Basaltbastion | 150 | 1650 | 27 | 1.4 | Klinge | Schwer | Erste 10 s: 25 % weniger Schaden, danach 10 %. | +| g05 | Funkenlanze | 65 | 240 | 24 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: 50 % zusätzlicher Grundschaden. | +| g06 | Glasballiste | 140 | 640 | 65 | 6.5 | Durchschlag | Leicht | Jeder 4. Treffer: 75 % zusätzlicher Grundschaden. | +| g07 | Aschenwerfer | 95 | 310 | 23 | 4.5 | Impuls | Leicht | Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m. | +| g08 | Kraterrufer | 190 | 820 | 58 | 5.0 | Impuls | Schwer | Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m. | +| g09 | Herdhüter | 85 | 420 | 12 | 3.5 | Impuls | Ätherisch | Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden. | +| g10 | Sonnenesse | 170 | 1080 | 30 | 4.0 | Impuls | Ätherisch | Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung. | +| w01 | Dornhopser | 50 | 290 | 18 | 1.1 | Klinge | Leicht | Jeder 3. Treffer: −20 % Bewegung für 2 s. | +| w02 | Rankenschnapper | 100 | 800 | 47 | 1.3 | Klinge | Schwer | Jeder 3. Treffer: −30 % Bewegung und −10 % Angriffstempo für 3 s. | +| w03 | Korkrücken | 75 | 620 | 12 | 1.2 | Durchschlag | Schwer | Heilt sich alle 5 s um 35 HP, sobald er verwundet ist. | +| w04 | Ringborke | 155 | 1560 | 31 | 1.4 | Durchschlag | Schwer | Heilt sich alle 5 s um 100 HP, sobald er verwundet ist. | +| w05 | Samenschleuder | 60 | 230 | 23 | 5.5 | Durchschlag | Leicht | Jeder 4. Treffer: Keimbrand, 3 Schaden/s für 4 s. | +| w06 | Zapfenkrone | 135 | 630 | 61 | 6.0 | Durchschlag | Leicht | Jeder 4. Treffer: Keimbrand, 10 Schaden/s für 4 s. | +| w07 | Sporenkelch | 100 | 370 | 22 | 4.0 | Impuls | Ätherisch | Jeder 3. Treffer: 60 % Grundschaden an bis zu 3 weiteren Zielen in 2 m. | +| w08 | Pilzkathedrale | 195 | 940 | 59 | 4.5 | Impuls | Ätherisch | Jeder 3. Treffer: 80 % Grundschaden an bis zu 4 weiteren Zielen in 2,5 m. | +| w09 | Tauhüter | 90 | 390 | 10 | 4.0 | Impuls | Leicht | Alle 4 s: heilt den am stärksten verwundeten Verbündeten in 4 m um 65 HP. | +| w10 | Quellgeflecht | 180 | 1000 | 27 | 4.5 | Impuls | Ätherisch | Alle 4 s: heilt bis zu 3 verwundete Verbündete in 4,5 m um je 80 HP. | + +## Wellen + +| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor | +| ---: | --- | --- | ---: | ---: | +| 1 | Erste Risse | 8 × Splitterling | 1.000 | 1.000 | +| 2 | Splitterstrom | 10 × Splitterling | 1.150 | 1.084 | +| 3 | Harte Schalen | 6 × Splitterling, 4 × Schalenläufer | 1.320 | 1.176 | +| 4 | Fäden im Rücken | 8 × Splitterling, 4 × Fadenschütze | 1.510 | 1.276 | +| 5 | Der Bruchhirsch | 1 × Bruchhirsch, 6 × Splitterling | 1.720 | 1.384 | +| 6 | Gepanzerter Vorstoß | 6 × Schalenläufer, 6 × Splitterling | 1.950 | 1.500 | +| 7 | Stimmen aus dem Nebel | 8 × Nebelrest, 4 × Splitterling | 2.200 | 1.624 | +| 8 | Der letzte Riegel | 1 × Riegelkoloss, 2 × Schalenläufer, 3 × Fadenschütze | 2.470 | 1.756 | + +## Standard gegen Lernmodus + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 22.3 | 3000 / 3000 | 0 / 0 | 112 / 177 | 4 / 3 | +| 3 | 32.1 | 3000 / 2733 | 0 / 5 | 156 / 191 | 4 / 3 | +| 4 | 22.1 | 3000 / 2380 | 0 / 11 | 137 / 176 | 5 / 3 | +| 5 | 36.4 | 3000 / 2091 | 0 / 2 | 166 / 199 | 7 / 4 | +| 6 | 36.9 | 3000 / 1716 | 0 / 9 | 192 / 171 | 7 / 6 | +| 7 | 46.6 | 3000 / 1584 | 0 / 4 | 193 / 179 | 8 / 6 | +| 8 | 50.0 | 3000 / 1035 | 0 / 5 | 211 / 162 | 9 / 6 | + +Ergebnis: Front 0 gewinnt. + +## Standard gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 3000 / 3000 | 0 / 0 | 139 / 139 | 3 / 3 | +| 2 | 13.3 | 3000 / 3000 | 0 / 0 | 112 / 112 | 4 / 4 | +| 3 | 27.3 | 3000 / 3000 | 0 / 0 | 157 / 157 | 4 / 4 | +| 4 | 23.2 | 3000 / 3000 | 0 / 0 | 142 / 142 | 5 / 5 | +| 5 | 17.7 | 3000 / 3000 | 0 / 0 | 156 / 156 | 5 / 5 | +| 6 | 22.1 | 3000 / 3000 | 0 / 0 | 190 / 190 | 5 / 5 | +| 7 | 20.8 | 3000 / 3000 | 0 / 0 | 182 / 182 | 6 / 6 | +| 8 | 25.0 | 3000 / 3000 | 0 / 0 | 244 / 244 | 6 / 6 | + +Ergebnis: Gleichstand. + +## Leeres Baufeld gegen Standard + +| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 | +| ---: | ---: | ---: | ---: | ---: | ---: | +| 1 | 13.3 | 2800 / 3000 | 8 / 0 | 295 / 139 | 0 / 3 | +| 2 | 13.3 | 2530 / 3000 | 10 / 0 | 373 / 112 | 0 / 4 | +| 3 | 20.0 | 2041 / 3000 | 11 / 0 | 454 / 150 | 0 / 4 | +| 4 | 20.1 | 1584 / 3000 | 13 / 0 | 538 / 151 | 0 / 5 | +| 5 | 15.3 | 1033 / 3000 | 8 / 0 | 625 / 161 | 0 / 5 | +| 6 | 18.1 | 304 / 3000 | 13 / 0 | 715 / 187 | 0 / 5 | +| 7 | 12.5 | 0 / 3000 | 12 / 0 | 715 / 37 | 0 / 5 | + +Ergebnis: Front 1 gewinnt. + +## Nachvollziehbarer Kaufplan gegen den Lernmodus + +Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern. + +| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs | +| ---: | --- | ---: | --- | +| 1 | Schlackenwacht, Funkenlanze, Kohlenbeißer | 0 | | +| 2 | Funkenlanze | 1 | | +| 3 | Schlackenklaue ↑ | 0 | s02 | +| 4 | Funkenlanze | 1 | s01 | +| 5 | Herdhüter, Kohlenbeißer | 0 | s01 | +| 6 | Glasballiste ↑ | 0 | s02 | +| 7 | Glasballiste ↑, Kohlenbeißer | 0 | s01 | +| 8 | Glasballiste ↑, Kohlenbeißer | 0 | s02 | diff --git a/docs/phase9-short-verification.json b/docs/phase9-short-verification.json new file mode 100644 index 0000000..5541cf4 --- /dev/null +++ b/docs/phase9-short-verification.json @@ -0,0 +1,714 @@ +{ + "capture": false, + "checks": 403, + "failures": [], + "matches": [ + { + "outcome": 0, + "title": "Standard gegen Lernmodus", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 177 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 3 + ], + "seconds": 22.3333333333333, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2733 + ], + "damage": [ + 0, + 267 + ], + "gold": [ + 156, + 191 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 3 + ], + "seconds": 32.1499999999995, + "sends": [ + "s02" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 2380 + ], + "damage": [ + 0, + 353 + ], + "gold": [ + 137, + 176 + ], + "leaks": [ + 0, + 11 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 3 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 2091 + ], + "damage": [ + 0, + 289 + ], + "gold": [ + 166, + 199 + ], + "leaks": [ + 0, + 2 + ], + "purchases": [ + "Herdhüter", + "Kohlenbeißer" + ], + "roster": [ + 7, + 4 + ], + "seconds": 36.4333333333325, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1716 + ], + "damage": [ + 0, + 375 + ], + "gold": [ + 192, + 171 + ], + "leaks": [ + 0, + 9 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 7, + 6 + ], + "seconds": 36.8999999999992, + "sends": [ + "s02" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1584 + ], + "damage": [ + 0, + 132 + ], + "gold": [ + 193, + 179 + ], + "leaks": [ + 0, + 4 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 8, + 6 + ], + "seconds": 46.5666666666653, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 1035 + ], + "damage": [ + 0, + 549 + ], + "gold": [ + 211, + 162 + ], + "leaks": [ + 0, + 5 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 9, + 6 + ], + "seconds": 49.9999999999984, + "sends": [ + "s02" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": -1, + "title": "Standard gegen Standard", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 139, + 139 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenwacht", + "Funkenlanze", + "Kohlenbeißer" + ], + "roster": [ + 3, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 112, + 112 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 4, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 157, + 157 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Schlackenklaue ↑" + ], + "roster": [ + 4, + 4 + ], + "seconds": 27.3333333333331, + "sends": [ + "s01", + "s01" + ], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 142, + 142 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Funkenlanze" + ], + "roster": [ + 5, + 5 + ], + "seconds": 23.25, + "sends": [ + "s01" + ], + "wave": 4, + "workers_ordered": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 156, + 156 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 17.6666666666669, + "sends": [ + "s01" + ], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 190, + 190 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑" + ], + "roster": [ + 5, + 5 + ], + "seconds": 22.1166666666667, + "sends": [ + "s01", + "s01" + ], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 182, + 182 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Glasballiste ↑", + "Kohlenbeißer" + ], + "roster": [ + 6, + 6 + ], + "seconds": 20.7833333333334, + "sends": [ + "s01" + ], + "wave": 7, + "workers_ordered": 0 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "damage": [ + 0, + 0 + ], + "gold": [ + 244, + 244 + ], + "leaks": [ + 0, + 0 + ], + "purchases": [ + "Basaltbastion ↑" + ], + "roster": [ + 6, + 6 + ], + "seconds": 24.9666666666665, + "sends": [ + "s01", + "s01" + ], + "wave": 8, + "workers_ordered": 0 + } + ] + }, + { + "outcome": 1, + "title": "Leeres Baufeld gegen Standard", + "waves": [ + { + "core_hp": [ + 2800, + 3000 + ], + "damage": [ + 200, + 0 + ], + "gold": [ + 295, + 139 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 3 + ], + "seconds": 13.2833333333336, + "sends": [], + "wave": 1, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2530, + 3000 + ], + "damage": [ + 270, + 0 + ], + "gold": [ + 373, + 112 + ], + "leaks": [ + 10, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 13.3333333333336, + "sends": [], + "wave": 2, + "workers_ordered": 0 + }, + { + "core_hp": [ + 2041, + 3000 + ], + "damage": [ + 489, + 0 + ], + "gold": [ + 454, + 150 + ], + "leaks": [ + 11, + 0 + ], + "purchases": [], + "roster": [ + 0, + 4 + ], + "seconds": 20.0333333333335, + "sends": [], + "wave": 3, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1584, + 3000 + ], + "damage": [ + 457, + 0 + ], + "gold": [ + 538, + 151 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 20.0666666666668, + "sends": [], + "wave": 4, + "workers_ordered": 0 + }, + { + "core_hp": [ + 1033, + 3000 + ], + "damage": [ + 551, + 0 + ], + "gold": [ + 625, + 161 + ], + "leaks": [ + 8, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 15.3333333333337, + "sends": [], + "wave": 5, + "workers_ordered": 0 + }, + { + "core_hp": [ + 304, + 3000 + ], + "damage": [ + 729, + 0 + ], + "gold": [ + 715, + 187 + ], + "leaks": [ + 13, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 18.1166666666669, + "sends": [], + "wave": 6, + "workers_ordered": 0 + }, + { + "core_hp": [ + 0, + 3000 + ], + "damage": [ + 304, + 0 + ], + "gold": [ + 715, + 37 + ], + "leaks": [ + 12, + 0 + ], + "purchases": [], + "roster": [ + 0, + 5 + ], + "seconds": 12.5000000000002, + "sends": [], + "wave": 7, + "workers_ordered": 0 + } + ] + } + ], + "wave_count": 8 +} \ No newline at end of file diff --git a/docs/phase9-verification.json b/docs/phase9-verification.json new file mode 100644 index 0000000..797ac07 --- /dev/null +++ b/docs/phase9-verification.json @@ -0,0 +1,5504 @@ +{ + "checks": 1659, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/docs/phase9-visual-verification.json b/docs/phase9-visual-verification.json new file mode 100644 index 0000000..7a418d4 --- /dev/null +++ b/docs/phase9-visual-verification.json @@ -0,0 +1,5504 @@ +{ + "checks": 1676, + "engine": "4.7.2-stable (fedora)", + "failures": [], + "matches": [ + { + "outcome": 1, + "title": "Wurzelbund gegen Glutpakt", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2811 + ], + "leaks": [ + 7, + 5 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 1954, + 2325 + ], + "leaks": [ + 10, + 7 + ], + "player_gold": 244, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 9, + 11 + ], + "player_gold": 242, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1798 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 298, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1709 + ], + "leaks": [ + 0, + 2 + ], + "player_gold": 338, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 5, + 0 + ], + "player_gold": 313, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 376, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 377, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 389, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 14 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 490, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 568, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 19 + } + ], + "seconds": 41.7999999999989, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1709 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 635, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 12 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(3, 1)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 14 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 16 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 17 + }, + { + "cell": "(5, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(2, 3)", + "invested": 295, + "target_policy": 0, + "type_id": "w08", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": 0, + "title": "Glutpakt gegen Wurzelbund", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 139, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 157, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 142, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.1000000000002, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 187, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + } + ], + "seconds": 19.9333333333335, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 192, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + } + ], + "seconds": 22.1833333333334, + "wave": 7 + }, + { + "core_hp": [ + 2811, + 2637 + ], + "leaks": [ + 5, + 7 + ], + "player_gold": 206, + "roster": [ + { + "cell": "(2, 0)", + "invested": 70, + "target_policy": 0, + "type_id": "g03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + } + ], + "seconds": 34.5499999999993, + "wave": 8 + }, + { + "core_hp": [ + 2325, + 1954 + ], + "leaks": [ + 7, + 10 + ], + "player_gold": 227, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 8 + } + ], + "seconds": 46.433333333332, + "wave": 9 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 11, + 9 + ], + "player_gold": 224, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 9 + } + ], + "seconds": 40.799999999999, + "wave": 10 + }, + { + "core_hp": [ + 1798, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 309, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 26.5666666666664, + "wave": 11 + }, + { + "core_hp": [ + 1709, + 1518 + ], + "leaks": [ + 2, + 0 + ], + "player_gold": 336, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 75.349999999997, + "wave": 12 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 5 + ], + "player_gold": 341, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 95, + "target_policy": 0, + "type_id": "g07", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 12 + } + ], + "seconds": 46.133333333332, + "wave": 14 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 422, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + } + ], + "seconds": 45.9999999999987, + "wave": 15 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 407, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 15 + } + ], + "seconds": 29.5166666666663, + "wave": 16 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 473, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 45, + "target_policy": 0, + "type_id": "g01", + "uid": 18 + } + ], + "seconds": 47.2499999999986, + "wave": 17 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 499, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 85, + "target_policy": 0, + "type_id": "g09", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + } + ], + "seconds": 37.7499999999991, + "wave": 18 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 550, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 20 + } + ], + "seconds": 41.8166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1709, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 620, + "roster": [ + { + "cell": "(2, 0)", + "invested": 220, + "target_policy": 0, + "type_id": "g04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 6 + }, + { + "cell": "(1, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 7 + }, + { + "cell": "(4, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 8 + }, + { + "cell": "(0, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 9 + }, + { + "cell": "(0, 2)", + "invested": 285, + "target_policy": 0, + "type_id": "g08", + "uid": 10 + }, + { + "cell": "(2, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 11 + }, + { + "cell": "(5, 2)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 14 + }, + { + "cell": "(2, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 16 + }, + { + "cell": "(4, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 255, + "target_policy": 0, + "type_id": "g10", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 205, + "target_policy": 0, + "type_id": "g06", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 135, + "target_policy": 0, + "type_id": "g02", + "uid": 22 + }, + { + "cell": "(0, 3)", + "invested": 65, + "target_policy": 0, + "type_id": "g05", + "uid": 23 + } + ], + "seconds": 61.7166666666644, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Spiegel", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 26.2833333333331, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 18.4666666666669, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.466666666667, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 17.5000000000003, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 199, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + } + ], + "seconds": 23.8666666666666, + "wave": 7 + }, + { + "core_hp": [ + 2637, + 2637 + ], + "leaks": [ + 7, + 7 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + } + ], + "seconds": 31.3333333333328, + "wave": 8 + }, + { + "core_hp": [ + 2087, + 2087 + ], + "leaks": [ + 8, + 8 + ], + "player_gold": 251, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + } + ], + "seconds": 45.4999999999987, + "wave": 9 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 11, + 11 + ], + "player_gold": 243, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + } + ], + "seconds": 37.3833333333325, + "wave": 10 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 295, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 25.5166666666665, + "wave": 11 + }, + { + "core_hp": [ + 1518, + 1518 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 339, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8999999999986, + "wave": 12 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 5, + 5 + ], + "player_gold": 314, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 44.2166666666654, + "wave": 13 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 373, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 35.8499999999992, + "wave": 14 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 424, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 11 + } + ], + "seconds": 47.8499999999986, + "wave": 15 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 406, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + } + ], + "seconds": 32.2666666666661, + "wave": 16 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 514, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 14 + } + ], + "seconds": 47.5666666666652, + "wave": 17 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 487, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 17 + } + ], + "seconds": 35.9166666666659, + "wave": 18 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 545, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 90, + "target_policy": 0, + "type_id": "w09", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 19 + } + ], + "seconds": 41.2166666666656, + "wave": 19 + }, + { + "core_hp": [ + 1244, + 1244 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 612, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(4, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 6 + }, + { + "cell": "(0, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 7 + }, + { + "cell": "(1, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 8 + }, + { + "cell": "(4, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 9 + }, + { + "cell": "(0, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 10 + }, + { + "cell": "(5, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 11 + }, + { + "cell": "(2, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 12 + }, + { + "cell": "(3, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 13 + }, + { + "cell": "(1, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 14 + }, + { + "cell": "(4, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 15 + }, + { + "cell": "(5, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 16 + }, + { + "cell": "(2, 3)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 17 + }, + { + "cell": "(0, 1)", + "invested": 270, + "target_policy": 0, + "type_id": "w10", + "uid": 18 + }, + { + "cell": "(5, 1)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 19 + }, + { + "cell": "(3, 3)", + "invested": 100, + "target_policy": 0, + "type_id": "w07", + "uid": 20 + }, + { + "cell": "(1, 3)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 21 + }, + { + "cell": "(4, 3)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 22 + } + ], + "seconds": 59.6333333333312, + "wave": 20 + } + ] + }, + { + "outcome": -1, + "title": "Wurzelbund Kurzpartie", + "waves": [ + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 134, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + } + ], + "seconds": 13.4666666666669, + "wave": 1 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 112, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 14.3333333333336, + "wave": 2 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 147, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 29.283333333333, + "wave": 3 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 152, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + } + ], + "seconds": 22.9833333333333, + "wave": 4 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 156, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.2000000000001, + "wave": 5 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 189, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 60, + "target_policy": 0, + "type_id": "w05", + "uid": 5 + } + ], + "seconds": 20.9833333333334, + "wave": 6 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 184, + "roster": [ + { + "cell": "(2, 0)", + "invested": 75, + "target_policy": 0, + "type_id": "w03", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 24.8999999999999, + "wave": 7 + }, + { + "core_hp": [ + 3000, + 3000 + ], + "leaks": [ + 0, + 0 + ], + "player_gold": 235, + "roster": [ + { + "cell": "(2, 0)", + "invested": 230, + "target_policy": 0, + "type_id": "w04", + "uid": 1 + }, + { + "cell": "(2, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 2 + }, + { + "cell": "(3, 0)", + "invested": 150, + "target_policy": 0, + "type_id": "w02", + "uid": 3 + }, + { + "cell": "(3, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 4 + }, + { + "cell": "(1, 2)", + "invested": 195, + "target_policy": 0, + "type_id": "w06", + "uid": 5 + }, + { + "cell": "(1, 0)", + "invested": 50, + "target_policy": 0, + "type_id": "w01", + "uid": 6 + } + ], + "seconds": 25.4166666666665, + "wave": 8 + } + ] + } + ], + "renderer": "forward_plus" +} \ No newline at end of file diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..4a3dc08 --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,69 @@ +[preset.0] +name="Linux" +platform="Linux" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="assets/phase3_manifest.json,assets/phase4_manifest.json,assets/phase11_manifest.json,assets/phase12_manifest.json,assets/phase15_manifest.json,assets/phase16_manifest.json,assets/phase18_manifest.json,assets/phase19_manifest.json,assets/menu_stage_manifest.json,assets/audio/manifest.json,assets/icons/manifest.json" +exclude_filter="docs/*,tests/*,tools/*,assets/ui/ui_*,assets/maps/*,assets/materials/phase11/*" +export_path="../dist/linux/Saumwacht.x86_64" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.0.options] +custom_template/debug="" +custom_template/release="res://assets-source/phase6/export-templates/linux_release.x86_64" +debug/export_console_wrapper=0 +binary_format/embed_pck=true +binary_format/architecture="x86_64" +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc2=false +texture_format/etc=false +codesign/enable=false +application/modify_resources=false +application/company_name="" +application/product_name="Saumwacht – Die zwei Bünde" +application/file_description="Saumwacht – Die zwei Bünde Demo" +application/file_version="0.15.0.0" +application/product_version="0.15.0.0" + +[preset.1] +name="Windows" +platform="Windows Desktop" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="assets/phase3_manifest.json,assets/phase4_manifest.json,assets/phase11_manifest.json,assets/phase12_manifest.json,assets/phase15_manifest.json,assets/phase16_manifest.json,assets/phase18_manifest.json,assets/phase19_manifest.json,assets/menu_stage_manifest.json,assets/audio/manifest.json,assets/icons/manifest.json" +exclude_filter="docs/*,tests/*,tools/*,assets/ui/ui_*,assets/maps/*,assets/materials/phase11/*" +export_path="../dist/windows/Saumwacht.exe" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.1.options] +custom_template/debug="" +custom_template/release="res://assets-source/phase6/export-templates/windows_release_x86_64.exe" +debug/export_console_wrapper=0 +binary_format/embed_pck=true +binary_format/architecture="x86_64" +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc2=false +texture_format/etc=false +codesign/enable=false +application/modify_resources=false +application/company_name="" +application/product_name="Saumwacht – Die zwei Bünde" +application/file_description="Saumwacht – Die zwei Bünde Demo" +application/file_version="0.15.0.0" +application/product_version="0.15.0.0" diff --git a/play.sh b/play.sh new file mode 100755 index 0000000..0e190bb --- /dev/null +++ b/play.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -euo pipefail +project_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +if command -v godot >/dev/null 2>&1; then + exec godot --path "$project_dir" "$@" +elif command -v godot4 >/dev/null 2>&1; then + exec godot4 --path "$project_dir" "$@" +else + echo "Godot 4 wurde nicht gefunden. Öffne project.godot mit Godot 4." >&2 + exit 1 +fi diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..246567e --- /dev/null +++ b/project.godot @@ -0,0 +1,49 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[animation] + +compatibility/default_parent_skeleton_in_mesh_instance_3d=true + +[application] + +config/name="Saumwacht · Glutpakt" +config/description="Glutpakt und Wurzelbund · 20 Wellen gegen die Rivalen-KI" +config/version="0.15.0" +run/main_scene="res://scenes/main.tscn" +config/features=PackedStringArray("4.7", "Forward Plus") +config/icon="res://assets/icons/resources/res_core.png" + +[autoload] + +AssetLibrary="*res://scripts/presentation/asset_library.gd" +DataCatalog="*res://scripts/data/data_catalog.gd" +GameState="*res://scripts/autoload/game_state.gd" +EconomyManager="*res://scripts/autoload/economy_manager.gd" +WaveManager="*res://scripts/autoload/wave_manager.gd" +Preferences="*res://scripts/autoload/preferences.gd" +Soundscape="*res://scripts/presentation/soundscape.gd" + +[display] + +window/size/viewport_width=1600 +window/size/viewport_height=960 +window/size/window_width_override=1440 +window/size/window_height_override=864 +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" +window/size/min_width=1152 +window/size/min_height=720 + +[rendering] + +renderer/rendering_method.mobile="gl_compatibility" +anti_aliasing/quality/msaa_3d=2 +environment/defaults/default_clear_color=Color(0.055, 0.073, 0.088, 1) diff --git a/scenes/main.tscn b/scenes/main.tscn new file mode 100644 index 0000000..90df94d --- /dev/null +++ b/scenes/main.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=4 format=3] + +[ext_resource type="Script" path="res://scripts/main.gd" id="1_main"] +[ext_resource type="Script" path="res://scripts/combat/battle_controller.gd" id="2_battle"] +[ext_resource type="Script" path="res://scripts/ui/hud.gd" id="3_hud"] + +[node name="Main" type="Node3D"] +script = ExtResource("1_main") + +[node name="World" type="Node3D" parent="."] + +[node name="Camera3D" type="Camera3D" parent="."] +projection = 1 +size = 33.0 +near = 0.1 +far = 250.0 +current = true + +[node name="BattleController" type="Node3D" parent="."] +script = ExtResource("2_battle") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="HUD" type="Control" parent="CanvasLayer"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("3_hud") diff --git a/scripts/ai/simple_ai.gd b/scripts/ai/simple_ai.gd new file mode 100644 index 0000000..c6b315a --- /dev/null +++ b/scripts/ai/simple_ai.gd @@ -0,0 +1,213 @@ +extends RefCounted +## Deterministic finite planning; no access to the opponent's current orders. + +const MAX_WORKERS_LEARNING := 4 +const MAX_ROSTER_LEARNING := 12 + +func plan(team: int, wave: int, opponent_snapshot: Dictionary, last_report: Dictionary, + level: int = GameState.AI_STANDARD) -> void: + if not EconomyManager.build_open or EconomyManager.current_wave != wave: + return + if wave == 1: + _order(team, {"type": "build", "type_id": "g03", "cell": Vector2i(2, 0)}) + _order(team, {"type": "build", "type_id": "g05", "cell": Vector2i(2, 2)}) + _order(team, {"type": "build", "type_id": "g01", "cell": Vector2i(3, 0)}) + return + if level == GameState.AI_LEARNING: + _plan_learning(team, wave) + return + var natural_count: int = maxi(1, int(last_report.get("natural_count", 1))) + var leak_ratio: float = float(last_report.get("natural_leaks", 0)) / float(natural_count) + var weak_front: bool = float(last_report.get("front_lifetime", 90.0)) < 12.0 or leak_ratio > 0.10 + var own: Dictionary = EconomyManager.get_team(team) + if own.is_empty(): + return + # Leave at least 60 gold for defense; newly ordered workers cannot produce now. + var cost: int = EconomyManager.worker_cost(team) + if not weak_front and wave <= DataCatalog.wave_count() - 3 and int(own["workers"]) + int(own["pending_workers"]) < 8: + if int(own["gold"]) >= cost + 60 and _front_count(own["roster"]) >= 2: + _order(team, {"type": "worker"}) + var armor: int = _dominant_wave_armor(wave) + # Fixed upper bound also makes pathological or full boards terminate immediately. + for _step: int in 16: + own = EconomyManager.get_team(team) + var roster: Array = own["roster"] + var front: int = _front_count(roster) + var desired_front: int = maxi(2, ceili(float(roster.size()) * 0.35)) + var purchased: bool = false + if front < desired_front: + purchased = _build(team, "g03" if front % 2 == 0 else "g01", own) + elif roster.size() >= 3: + purchased = _upgrade(team, own, armor, weak_front) + if not purchased: + var preferred: Array[String] = _buy_preferences(roster, armor, weak_front) + for id: String in preferred: + if _build(team, id, own): + purchased = true + break + if not purchased: + break + _plan_sends(team, wave, opponent_snapshot) + + +func _plan_learning(team: int, wave: int) -> void: + # Fixed, readable behaviour: no reactive counters, no saved-up attacks. + var own: Dictionary = EconomyManager.get_team(team) + if own.is_empty(): + return + var cost: int = EconomyManager.worker_cost(team) + if wave <= DataCatalog.wave_count() - 3 and int(own["workers"]) + int(own["pending_workers"]) < MAX_WORKERS_LEARNING: + if int(own["gold"]) >= cost + 60 and _front_count(own["roster"]) >= 2: + _order(team, {"type": "worker"}) + var rotation: Array[String] = ["g03", "g01", "g05", "g07", "g09"] + var upgrade_order: Array[String] = ["g03", "g05", "g01", "g07", "g09"] + for _step: int in 16: + own = EconomyManager.get_team(team) + var roster: Array = own["roster"] + var purchased: bool = false + if roster.size() >= 6: + purchased = _upgrade_any(team, own, upgrade_order) + if not purchased and roster.size() < MAX_ROSTER_LEARNING: + purchased = _build(team, rotation[roster.size() % rotation.size()], own) + if not purchased: + break + _plan_simple_sends(team, wave) + + +func _upgrade_any(team: int, own: Dictionary, order: Array[String]) -> bool: + for id: String in order: + var upgraded: Dictionary = DataCatalog.get_unit(DataCatalog.UNITS[DataCatalog.for_team(id, team)]["upgrade_id"]) + if int(own["gold"]) < int(upgraded["cost"]): + continue + for entry: Dictionary in own["roster"]: + if entry["type_id"] == DataCatalog.for_team(id, team): + return _order(team, {"type": "upgrade", "uid": entry["uid"]}) + return false + + +func _plan_simple_sends(team: int, wave: int) -> void: + # Sends only in every second allowed wave; the budget is spent immediately. + if wave < 3 or wave % 2 == 0: + return + for _step: int in 8: + var own: Dictionary = EconomyManager.get_team(team) + var reserved: int = EconomyManager.reserved_sparks(team) + var available: int = mini(int(own["sparks"]) - reserved, EconomyManager.send_budget(wave) - reserved) + if own["send_queue"].size() >= 8 or available < 20: + break + var send_id: String = "s01" if available < 40 else "s02" + if not _order(team, {"type": "queue_send", "type_id": send_id}): + break + +func _buy_preferences(roster: Array, armor: int, weak_front: bool) -> Array[String]: + var front: int = _front_count(roster) + if front < 2 or (weak_front and front * 2 < roster.size()): + return ["g03", "g01", "g05"] + var support: int = _count_types(roster, ["g09", "g10"]) + if roster.size() >= 4 and support * 4 < roster.size() and not weak_front: + return ["g09", "g05", "g07", "g01"] + if armor == 2 or _count_types(roster, ["g07", "g08"]) == 0: + return ["g07", "g05", "g01"] + return ["g05", "g07", "g01"] + +func _upgrade(team: int, own: Dictionary, armor: int, weak_front: bool) -> bool: + var order: Array[String] = ["g05", "g03", "g07", "g01", "g09"] + if weak_front: + order = ["g03", "g01", "g05", "g07", "g09"] + elif armor == 2: + order = ["g07", "g05", "g03", "g01", "g09"] + for id: String in order: + var upgraded: Dictionary = DataCatalog.get_unit(DataCatalog.UNITS[DataCatalog.for_team(id, team)]["upgrade_id"]) + if int(own["gold"]) < int(upgraded["cost"]): + continue + for entry: Dictionary in own["roster"]: + if entry["type_id"] == DataCatalog.for_team(id, team): + return _order(team, {"type": "upgrade", "uid": entry["uid"]}) + return false + +func _build(team: int, id: String, own: Dictionary) -> bool: + var definition: Dictionary = DataCatalog.get_unit(DataCatalog.for_team(id, team)) + if int(own["gold"]) < int(definition["cost"]): + return false + var cell: Vector2i = _free_cell(own["roster"], id) + if cell.x < 0: + return false + return _order(team, {"type": "build", "type_id": id, "cell": cell}) + +func _free_cell(roster: Array, id: String) -> Vector2i: + var rows: Array[int] = [2, 3, 4, 5, 6, 7, 1, 0] + if id in ["g01", "g03"]: + rows = [0, 1, 2, 3, 4, 5, 6, 7] + elif id == "g09": + rows = [1, 2, 3, 4, 5, 6, 7, 0] + for row: int in rows: + for column: int in [2, 3, 1, 4, 0, 5]: + var candidate: Vector2i = Vector2i(column, row) + var occupied: bool = false + for entry: Dictionary in roster: + if entry["cell"] == candidate: + occupied = true + break + if not occupied: + return candidate + return Vector2i(-1, -1) + +func _plan_sends(team: int, wave: int, opponent_snapshot: Dictionary) -> void: + if wave < 3: + return + var public_roster: Array = opponent_snapshot.get("roster", []) + var upgraded: int = 0 + var pierce_damage: float = 0.0 + for entry: Dictionary in public_roster: + var definition: Dictionary = DataCatalog.get_unit(str(entry.get("type_id", ""))) + if definition.is_empty(): + continue + if str(definition["upgrade_id"]).is_empty(): + upgraded += 1 + if int(definition["attack_type"]) == 1: + pierce_damage += float(definition["damage"]) + for _step: int in 8: + var own: Dictionary = EconomyManager.get_team(team) + var reserved: int = EconomyManager.reserved_sparks(team) + var available: int = mini(int(own["sparks"]) - reserved, EconomyManager.send_budget(wave) - reserved) + if own["send_queue"].size() >= 8 or available < 20: + break + var send_id: String = "s01" + if wave >= 11 and available >= 200 and _count_types(public_roster, ["g10"]) > 0: + send_id = "s05" + elif wave >= 6 and available >= 130 and _front_count(public_roster) >= 3: + send_id = "s04" + elif available >= 80 and upgraded >= 2 and public_roster.size() <= 6: + send_id = "s03" + elif available >= 40 and pierce_damage < 40.0: + send_id = "s02" + if not _order(team, {"type": "queue_send", "type_id": send_id}): + break + +func _dominant_wave_armor(wave: int) -> int: + var armor_weight: Array[float] = [0.0, 0.0, 0.0] + for enemy: Dictionary in DataCatalog.get_attackers(wave): + armor_weight[int(enemy["armor_type"])] += float(enemy["max_hp"]) + var result: int = 0 + for index: int in range(1, 3): + if armor_weight[index] > armor_weight[result]: + result = index + return result + +func _front_count(roster: Array) -> int: + return _count_types(roster, ["g01", "g02", "g03", "g04"]) + +func _count_types(roster: Array, ids: Array) -> int: + var count: int = 0 + for entry: Dictionary in roster: + var id: String = str(entry.get("type_id", "")) + if id.begins_with("w"): + id = "g" + id.substr(1) + if ids.has(id): + count += 1 + return count + +func _order(team: int, command: Dictionary) -> bool: + if command.has("type_id"): + command["type_id"] = DataCatalog.for_team(str(command["type_id"]), team) + return bool(EconomyManager.apply_command(team, command)["ok"]) diff --git a/scripts/ai/simple_ai.gd.uid b/scripts/ai/simple_ai.gd.uid new file mode 100644 index 0000000..8a00e47 --- /dev/null +++ b/scripts/ai/simple_ai.gd.uid @@ -0,0 +1 @@ +uid://dlsr1k88ptdqu diff --git a/scripts/autoload/economy_manager.gd b/scripts/autoload/economy_manager.gd new file mode 100644 index 0000000..7f16fa6 --- /dev/null +++ b/scripts/autoload/economy_manager.gd @@ -0,0 +1,268 @@ +extends Node +## All player and AI orders use this transaction boundary. + +signal changed(team: int) + +const TEAM_COUNT: int = 2 +const GRID_SIZE: Vector2i = Vector2i(6, 8) +const MAX_WORKERS: int = 8 +const MAX_SENDS: int = 8 +const SPARK_CAP: int = 400 + +var teams: Array = [] +var current_wave: int = 0 +var build_open: bool = false +var _histories: Array = [[], []] +var _next_ids: Array[int] = [1, 1] +var _opened_waves: Dictionary = {} +var _frozen_batches: Dictionary = {} +var _settlements: Dictionary = {} + +func _ready() -> void: + reset_match() + +func reset_match() -> void: + teams.clear() + for team: int in TEAM_COUNT: + var empty_queue: Array[String] = [] + teams.append({"faction": GameState.factions[team], "gold": 220, "sparks": 0, "income": 20, "workers": 1, + "pending_workers": 0, "roster": [], "send_queue": empty_queue}) + _histories = [[], []] + _next_ids = [1, 1] + _opened_waves.clear() + _frozen_batches.clear() + _settlements.clear() + current_wave = 0 + build_open = false + for team: int in TEAM_COUNT: + changed.emit(team) + +func get_team(team: int) -> Dictionary: + if not _valid_team(team): + return {} + return teams[team].duplicate(true) + +func open_build(wave: int) -> void: + # Repeated phase callbacks never produce more resources or unlock a frozen wave. + if wave < 1 or wave > DataCatalog.wave_count() or _opened_waves.has(wave): + return + if wave != current_wave + 1 or (current_wave > 0 and not _frozen_batches.has(current_wave)): + return + current_wave = wave + build_open = true + _opened_waves[wave] = true + _histories = [[], []] + for team: int in TEAM_COUNT: + var state: Dictionary = teams[team] + state["workers"] += int(state["pending_workers"]) + state["pending_workers"] = 0 + state["sparks"] = mini(SPARK_CAP, int(state["sparks"]) + 10 * int(state["workers"])) + changed.emit(team) + +func freeze(wave: int) -> Array: + if _frozen_batches.has(wave): + return _frozen_batches[wave].duplicate(true) + if not build_open or wave != current_wave: + return [[], []] + # Close commands before either side is committed or notified. + build_open = false + var batches: Array = [[], []] + for team: int in TEAM_COUNT: + var state: Dictionary = teams[team] + batches[team] = state["send_queue"].duplicate() + state["sparks"] -= reserved_sparks(team) + for id: String in state["send_queue"]: + state["income"] += int(DataCatalog.SENDS[id]["income_gain"]) + state["send_queue"].clear() + _frozen_batches[wave] = batches.duplicate(true) + _histories = [[], []] + for team: int in TEAM_COUNT: + changed.emit(team) + return batches + +func settle(team: int, wave: int, bounty: int) -> Dictionary: + if not _valid_team(team) or not _frozen_batches.has(wave): + return {} + var key: String = "%d:%d" % [team, wave] + if _settlements.has(key): + return _settlements[key].duplicate(true) + # An old wave cannot be first settled after a newer wave has started. + if current_wave != wave or build_open: + return {} + var state: Dictionary = teams[team] + var base_gold: int = 55 + 3 * (wave - 1) + var earned_bounty: int = maxi(0, bounty) + var total: int = base_gold + int(state["income"]) + earned_bounty + state["gold"] += total + var report: Dictionary = {"team": team, "wave": wave, "base_gold": base_gold, + "income": state["income"], "bounty": earned_bounty, "total_gold": total, + "total": total, "gold": state["gold"]} + _settlements[key] = report.duplicate(true) + changed.emit(team) + return report + +func reserved_sparks(team: int) -> int: + if not _valid_team(team): + return 0 + var reserved: int = 0 + for id: String in teams[team]["send_queue"]: + reserved += int(DataCatalog.SENDS[id]["cost"]) + return reserved + +func worker_cost(team: int) -> int: + if not _valid_team(team): + return 0 + var owned: int = int(teams[team]["workers"]) + int(teams[team]["pending_workers"]) + return 70 + 20 * (owned - 1) + +func send_budget(wave: int) -> int: + return 60 + 15 * (wave - 1) if wave >= 1 and wave <= DataCatalog.wave_count() else 0 + +func apply_command(team: int, command: Dictionary) -> Dictionary: + if not _valid_team(team): + return _result(false, "Ungültiges Team.") + if not build_open: + return _result(false, "Befehle sind nur in der Bauphase möglich.") + var kind: String = str(command.get("type", "")) + if kind == "undo": + if _histories[team].is_empty(): + return _result(false, "Keine Aktion zum Rückgängigmachen.") + teams[team] = _histories[team].pop_back() + changed.emit(team) + return _result(true, "Letzte Aktion zurückgenommen.") + var before: Dictionary = teams[team].duplicate(true) + var result: Dictionary = _execute(team, kind, command) + if result["ok"]: + _histories[team].append(before) + changed.emit(team) + return result + +func _execute(team: int, kind: String, command: Dictionary) -> Dictionary: + var state: Dictionary = teams[team] + var roster: Array = state["roster"] + match kind: + "build": + var type_id: String = str(command.get("type_id", "")) + if not DataCatalog.faction_ids(str(state["faction"])).has(type_id): + return _result(false, "Nur Basiseinheiten können gekauft werden.") + if not _valid_cell(command.get("cell")): + return _result(false, "Wähle ein Feld im 6 × 8 Baufeld.") + var cell: Vector2i = command["cell"] + if _occupied(roster, cell): + return _result(false, "Dieses Feld ist bereits belegt.") + var definition: Dictionary = DataCatalog.get_unit(type_id) + var cost: int = int(definition["cost"]) + if int(state["gold"]) < cost: + return _missing_gold(cost - int(state["gold"])) + state["gold"] -= cost + # IDs remain monotonic across undo; team namespaces prevent collisions. + var uid: int = team * 1000000 + _next_ids[team] + _next_ids[team] += 1 + roster.append({"uid": uid, "type_id": type_id, "cell": cell, + "invested": cost, "target_policy": 0}) + return _result(true, "%s gebaut." % definition["display_name"]) + "upgrade", "sell", "move", "target": + if typeof(command.get("uid")) != TYPE_INT: + return _result(false, "Keine gültige Einheit ausgewählt.") + var index: int = _unit_index(roster, int(command["uid"])) + if index < 0: + return _result(false, "Die ausgewählte Einheit gehört nicht zu diesem Team.") + var entry: Dictionary = roster[index] + if kind == "upgrade": + var definition: Dictionary = DataCatalog.get_unit(entry["type_id"]) + var upgrade_id: String = definition["upgrade_id"] + if upgrade_id.is_empty(): + return _result(false, "Diese Einheit ist bereits vollständig aufgewertet.") + var upgrade: Dictionary = DataCatalog.get_unit(upgrade_id) + var cost: int = int(upgrade["cost"]) + if int(state["gold"]) < cost: + return _missing_gold(cost - int(state["gold"])) + state["gold"] -= cost + entry["type_id"] = upgrade_id + entry["invested"] += cost + return _result(true, "Zu %s aufgewertet." % upgrade["display_name"]) + if kind == "sell": + var refund: int = floori(float(entry["invested"]) * 0.75) + state["gold"] += refund + roster.remove_at(index) + return _result(true, "Einheit für %d Gold verkauft." % refund) + if kind == "move": + if not _valid_cell(command.get("cell")): + return _result(false, "Wähle ein Feld im 6 × 8 Baufeld.") + var cell: Vector2i = command["cell"] + if _occupied(roster, cell): + return _result(false, "Dieses Feld ist bereits belegt.") + entry["cell"] = cell + return _result(true, "Einheit versetzt.") + if typeof(command.get("policy")) != TYPE_INT: + return _result(false, "Ungültige Zielwahl.") + var policy: int = int(command["policy"]) + if policy < 0 or policy > 2: + return _result(false, "Ungültige Zielwahl.") + if policy == int(entry["target_policy"]): + return _result(false, "Diese Zielwahl ist bereits aktiv.") + entry["target_policy"] = policy + return _result(true, "Zielwahl geändert.") + "worker": + if current_wave >= DataCatalog.wave_count(): + return _result(false, "In der letzten Welle produzieren neue Arbeiter keine Funken mehr.") + if int(state["workers"]) + int(state["pending_workers"]) >= MAX_WORKERS: + return _result(false, "Das Maximum von 8 Arbeitern ist erreicht.") + var cost: int = worker_cost(team) + if int(state["gold"]) < cost: + return _missing_gold(cost - int(state["gold"])) + state["gold"] -= cost + state["pending_workers"] += 1 + return _result(true, "Funkenleser bestellt; aktiv ab der nächsten Bauphase.") + "queue_send": + if current_wave < 3: + return _result(false, "Söldner sind ab Welle 3 verfügbar.") + var type_id: String = str(command.get("type_id", "")) + if not DataCatalog.SENDS.has(type_id): + return _result(false, "Unbekannter Söldner.") + if state["send_queue"].size() >= MAX_SENDS: + return _result(false, "Höchstens 8 Söldner pro Welle.") + var cost: int = int(DataCatalog.SENDS[type_id]["cost"]) + var reserved: int = reserved_sparks(team) + if reserved + cost > send_budget(current_wave): + return _result(false, "Das Funkenbudget dieser Welle reicht nicht aus.") + if reserved + cost > int(state["sparks"]): + return _result(false, "Es fehlen %d freie Funken." % (reserved + cost - int(state["sparks"]))) + state["send_queue"].append(type_id) + return _result(true, "%s vorgemerkt." % DataCatalog.SENDS[type_id]["display_name"]) + "cancel_send": + if typeof(command.get("index")) != TYPE_INT: + return _result(false, "Ungültiger Söldnerauftrag.") + var index: int = int(command["index"]) + if index < 0 or index >= state["send_queue"].size(): + return _result(false, "Ungültiger Söldnerauftrag.") + state["send_queue"].remove_at(index) + return _result(true, "Söldnerauftrag entfernt; Funken wieder frei.") + return _result(false, "Unbekannter Befehl.") + +func _valid_team(team: int) -> bool: + return team >= 0 and team < TEAM_COUNT and teams.size() == TEAM_COUNT + +func _valid_cell(value: Variant) -> bool: + if typeof(value) != TYPE_VECTOR2I: + return false + var cell: Vector2i = value + return cell.x >= 0 and cell.x < GRID_SIZE.x and cell.y >= 0 and cell.y < GRID_SIZE.y + +func _occupied(roster: Array, cell: Vector2i) -> bool: + for entry: Dictionary in roster: + if entry["cell"] == cell: + return true + return false + +func _unit_index(roster: Array, uid: int) -> int: + for index: int in roster.size(): + if int(roster[index]["uid"]) == uid: + return index + return -1 + +func _missing_gold(missing: int) -> Dictionary: + return _result(false, "Es fehlen %d Gold." % missing) + +func _result(ok: bool, message: String) -> Dictionary: + return {"ok": ok, "message": message} diff --git a/scripts/autoload/economy_manager.gd.uid b/scripts/autoload/economy_manager.gd.uid new file mode 100644 index 0000000..eda40d9 --- /dev/null +++ b/scripts/autoload/economy_manager.gd.uid @@ -0,0 +1 @@ +uid://roivdkv5rkre diff --git a/scripts/autoload/game_state.gd b/scripts/autoload/game_state.gd new file mode 100644 index 0000000..f1e5cf3 --- /dev/null +++ b/scripts/autoload/game_state.gd @@ -0,0 +1,83 @@ +extends Node +## Persistent match state. Only WaveManager advances phases or resolves results. + +signal phase_changed(phase: int) +signal changed + +enum Phase { MENU, BUILD, COMBAT, RESULTS, GAME_OVER } + +const CORE_MAX_HP := 3000 +const ONGOING := -2 +const DRAW := -1 +const AI_LEARNING := 0 +const AI_STANDARD := 1 +const MODE_SHORT := "short" +const MODE_EXPEDITION := "expedition" + +var phase: int = Phase.MENU +var wave: int = 0 +var core_hp: Array = [CORE_MAX_HP, CORE_MAX_HP] +var paused: bool = false +var speed: int = 1 +var outcome: int = ONGOING +var last_reports: Array = [{}, {}] +var ai_level: int = AI_LEARNING +var timed_build: bool = false +var factions: Array[String] = ["wurzelbund", "glutpakt"] +var match_mode: String = MODE_EXPEDITION + + +func select_mode(value: String) -> bool: + if phase not in [Phase.MENU, Phase.GAME_OVER] or value not in [MODE_SHORT, MODE_EXPEDITION]: + return false + match_mode = value + changed.emit() + return true + + +func reset_match() -> void: + wave = 0 + core_hp = [CORE_MAX_HP, CORE_MAX_HP] + paused = false + speed = 1 + outcome = ONGOING + last_reports = [{}, {}] + set_phase(Phase.MENU) + + +func set_phase(next_phase: int) -> void: + phase = next_phase + phase_changed.emit(phase) + changed.emit() + + +func apply_core_damage(damage: Array) -> void: + # Both lanes are applied before anyone checks the winner. + for team in range(2): + core_hp[team] = maxi(0, int(core_hp[team]) - maxi(0, int(damage[team]))) + changed.emit() + + +func decide_winner(final_wave: bool = false) -> int: + if core_hp[0] <= 0 and core_hp[1] <= 0: + return DRAW + if core_hp[0] <= 0: + return 1 + if core_hp[1] <= 0: + return 0 + if not final_wave: + return ONGOING + if core_hp[0] == core_hp[1]: + return DRAW + return 0 if core_hp[0] > core_hp[1] else 1 + + +func phase_name() -> String: + return ["VORBEREITUNG", "BAUPHASE", "AUTOKAMPF", "ABRECHNUNG", "PARTIE BEENDET"][phase] + +func select_faction(team: int, faction: String) -> bool: + if phase not in [Phase.MENU, Phase.GAME_OVER] or team < 0 or team > 1 or faction not in DataCatalog.FACTIONS: + return false + factions[team] = faction + changed.emit() + return true diff --git a/scripts/autoload/game_state.gd.uid b/scripts/autoload/game_state.gd.uid new file mode 100644 index 0000000..1fe85d3 --- /dev/null +++ b/scripts/autoload/game_state.gd.uid @@ -0,0 +1 @@ +uid://bb4ro0570fa1m diff --git a/scripts/autoload/preferences.gd b/scripts/autoload/preferences.gd new file mode 100644 index 0000000..6307d19 --- /dev/null +++ b/scripts/autoload/preferences.gd @@ -0,0 +1,45 @@ +extends Node +## Local preferences only. Match rules and ownership are never saved here. + +signal changed +var volume: float = .65 +var muted: bool = false +var follow_camera: bool = true +var fullscreen: bool = false +## Menu camera travel, idle drift, particles and fades are skipped when set. +var reduced_motion: bool = false +var storage_path: String = "user://preferences.cfg" + +func _ready() -> void: + read_settings() + apply() + +func read_settings() -> void: + var config := ConfigFile.new() + if config.load(storage_path) != OK: + return + volume = clampf(float(config.get_value("audio", "volume", .65)), 0.0, 1.0) + muted = bool(config.get_value("audio", "muted", false)) + follow_camera = bool(config.get_value("camera", "follow", true)) + fullscreen = bool(config.get_value("display", "fullscreen", false)) + reduced_motion = bool(config.get_value("display", "reduced_motion", false)) + +func apply() -> void: + AudioServer.set_bus_volume_db(0, linear_to_db(maxf(.001, volume))) + AudioServer.set_bus_mute(0, muted or volume <= 0.0) + if DisplayServer.get_name() != "headless": + DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if fullscreen else DisplayServer.WINDOW_MODE_WINDOWED) + changed.emit() + +func save_settings() -> Error: + var config := ConfigFile.new() + config.set_value("audio", "volume", volume) + config.set_value("audio", "muted", muted) + config.set_value("camera", "follow", follow_camera) + config.set_value("display", "fullscreen", fullscreen) + config.set_value("display", "reduced_motion", reduced_motion) + return config.save(storage_path) + +func commit() -> void: + apply() + save_settings() diff --git a/scripts/autoload/preferences.gd.uid b/scripts/autoload/preferences.gd.uid new file mode 100644 index 0000000..8f00169 --- /dev/null +++ b/scripts/autoload/preferences.gd.uid @@ -0,0 +1 @@ +uid://5okn6yofgamo diff --git a/scripts/autoload/wave_manager.gd b/scripts/autoload/wave_manager.gd new file mode 100644 index 0000000..994fd8b --- /dev/null +++ b/scripts/autoload/wave_manager.gd @@ -0,0 +1,152 @@ +extends Node +## Single authoritative phase coordinator; the presentation never ticks combat. + +signal updated +signal battle_started +signal wave_settled(reports: Array) + +const AI_SCRIPT = preload("res://scripts/ai/simple_ai.gd") +const BUILD_FIRST := 45.0 +const BUILD_DURATION := 30.0 +const RESULTS_DURATION := 4.0 + +var battle: Node3D +var remaining: float = 0.0 +var ai = AI_SCRIPT.new() +var _public_snapshots: Array = [{}, {}] +var _wave_core_damage: Array = [0, 0] + + +func attach_battle(controller: Node3D) -> void: + battle = controller + + +func start_match() -> void: + if not is_instance_valid(battle): + push_error("WaveManager needs an attached BattleController.") + return + GameState.reset_match() + EconomyManager.reset_match() + _public_snapshots = [EconomyManager.get_team(0), EconomyManager.get_team(1)] + GameState.wave = 1 + _open_build() + + +func _open_build() -> void: + EconomyManager.open_build(GameState.wave) + GameState.set_phase(GameState.Phase.BUILD) + remaining = BUILD_FIRST if GameState.wave == 1 else BUILD_DURATION + # The rival uses the previous completed formation, never a live player queue. + ai.plan(1, GameState.wave, _public_snapshots[0], GameState.last_reports[1], GameState.ai_level) + battle.show_formation(_rosters()) + updated.emit() + + +func _rosters() -> Array: + return [EconomyManager.get_team(0).roster, EconomyManager.get_team(1).roster] + + +func ready_for_battle() -> void: + if GameState.phase == GameState.Phase.RESULTS: + _next_wave() + return + if GameState.phase != GameState.Phase.BUILD: + return + _public_snapshots = [EconomyManager.get_team(0), EconomyManager.get_team(1)] + var outgoing: Array = EconomyManager.freeze(GameState.wave) + var attackers: Array = [ + DataCatalog.get_attackers(GameState.wave), + DataCatalog.get_attackers(GameState.wave) + ] + for sender in range(2): + for send_id in outgoing[sender]: + attackers[1 - sender].append(DataCatalog.get_send(str(send_id), GameState.wave)) + _wave_core_damage = [0, 0] + battle.begin_battle(_rosters(), attackers, GameState.wave) + remaining = 90.0 + GameState.set_phase(GameState.Phase.COMBAT) + battle_started.emit() + updated.emit() + + +func _physics_process(delta: float) -> void: + if GameState.paused: + return + # 2x repeats the same fixed step rather than doubling its integration delta. + for _substep in range(GameState.speed): + advance(delta) + + +func advance(delta: float) -> void: + if delta <= 0.0 or GameState.paused: + return + match GameState.phase: + GameState.Phase.BUILD: + if not GameState.timed_build: + return + remaining = maxf(0.0, remaining - delta) + if remaining <= 0.0: + ready_for_battle() + GameState.Phase.COMBAT: + var report: Dictionary = battle.step(delta) + remaining = maxf(0.0, 90.0 - float(report.elapsed)) + var leak_damage: Array = report.leak_damage + if leak_damage[0] > 0 or leak_damage[1] > 0: + for team in range(2): + _wave_core_damage[team] += int(leak_damage[team]) + GameState.apply_core_damage(leak_damage) + for lane: int in range(2): + if leak_damage[lane] > 0: + Soundscape.play("leak", lane) + var winner: int = GameState.decide_winner(false) + if winner != GameState.ONGOING: + _finish_match(winner) + elif report.finished: + _settle(report) + GameState.Phase.RESULTS: + if not GameState.timed_build: + return + remaining = maxf(0.0, remaining - delta) + if remaining <= 0.0: + _next_wave() + + +func _settle(combat_report: Dictionary) -> void: + var reports: Array = [] + for team in range(2): + var report: Dictionary = EconomyManager.settle( + team, GameState.wave, int(combat_report.bounties[team])) + report["leaks"] = combat_report.leaks[team] + report["core_damage"] = _wave_core_damage[team] + report["combat_seconds"] = combat_report.elapsed + report["natural_count"] = DataCatalog.get_attackers(GameState.wave).size() + report["natural_leaks"] = combat_report.get("natural_leaks", combat_report.leaks)[team] + report["front_lifetime"] = combat_report.get("front_lifetime", [90.0, 90.0])[team] + reports.append(report) + GameState.last_reports = reports + wave_settled.emit(reports) + if GameState.wave >= DataCatalog.wave_count(): + _finish_match(GameState.decide_winner(true)) + else: + remaining = RESULTS_DURATION + GameState.set_phase(GameState.Phase.RESULTS) + updated.emit() + + +func _next_wave() -> void: + if GameState.phase != GameState.Phase.RESULTS: + return + GameState.wave += 1 + _open_build() + + +func _finish_match(winner: int) -> void: + GameState.outcome = winner + GameState.paused = false + remaining = 0.0 + GameState.set_phase(GameState.Phase.GAME_OVER) + updated.emit() + + +func rival_snapshot() -> Dictionary: + return _public_snapshots[1].duplicate(true) diff --git a/scripts/autoload/wave_manager.gd.uid b/scripts/autoload/wave_manager.gd.uid new file mode 100644 index 0000000..3847434 --- /dev/null +++ b/scripts/autoload/wave_manager.gd.uid @@ -0,0 +1 @@ +uid://cno7d86m83v7f diff --git a/scripts/combat/ability_component.gd b/scripts/combat/ability_component.gd new file mode 100644 index 0000000..711cec4 --- /dev/null +++ b/scripts/combat/ability_component.gd @@ -0,0 +1,121 @@ +extends RefCounted +## Shared content abilities: Glutpakt, ten neutral archetypes and five sends. + +var ready_time: float = 6.0 +var _opening_pose_pending: bool = false + +func start(unit) -> void: + match str(unit.data.ability): + "g04": _opening_pose_pending = true + "w03", "w04": ready_time = 5.0 + "w09", "w10": ready_time = 4.0 + "s02": unit.grant_shield(unit.max_hp * 0.15) + "e08": unit.grant_shield(unit.max_hp * 0.20) + +func step(unit, combatants: Array, _delta: float) -> void: + # Formation previews also call start(); defer the passive pose to combat. + if _opening_pose_pending and unit.combat_time > 0.0: + _opening_pose_pending = false + unit.play_ability() + if unit.combat_time + 0.000001 < ready_time: + return + var ability = str(unit.data.ability) + var success = false + match ability: + "w03", "w04": + if unit.hp < unit.max_hp: + unit.heal(100.0 if ability == "w04" else 35.0) + success = true + "w09", "w10": + var upgraded = ability == "w10" + var allies = nearby(unit, combatants, true, unit.position, 4.5 if upgraded else 4.0, 3 if upgraded else 1, null, true) + for ally in allies: + if ally.hp < ally.max_hp: + ally.heal(80.0 if upgraded else 65.0) + ally.ability_flash = 0.5 + success = true + "g09", "g10": + var upgraded = ability == "g10" + var allies = nearby(unit, combatants, true, unit.position, 4.0 if upgraded else 3.0, 4 if upgraded else 3, null, true) + for ally in allies: + ally.apply_effect("hearth_warmth", "damage", 0.15 if upgraded else 0.10, 4.0) + if upgraded: + ally.heal(45.0) + success = not allies.is_empty() + "e06": + var allies = nearby(unit, combatants, true, unit.position, 4.0, 100, null, true) + for ally in allies: + if ally.hp < ally.max_hp: + # Derive the HP-wave factor exactly, not from rounded max HP. + ally.heal(30.0 * float(unit.data.get("hp_factor", 1.0))) + success = true + break + "s03", "e09": + var boss = ability == "e09" + var victims = nearby(unit, combatants, false, unit.position, 6.0 if boss else 3.0, 3 if boss else 4) + for victim in victims: + victim.apply_effect("dissonance", "attack_slow", 0.15, 3.0) + success = not victims.is_empty() + "s05": + var victims = nearby(unit, combatants, false, unit.position, 5.0, 1) + for victim in victims: + victim.apply_effect("rift_wound", "healing_reduction", 0.30, 4.0) + success = not victims.is_empty() + if success: + ready_time = unit.combat_time + (5.0 if ability in ["w03", "w04"] else (4.0 if ability in ["w09", "w10"] else 6.0)) + unit.play_ability() + +func on_hit(unit, primary, combatants: Array, hit_count: int) -> void: + var ability = str(unit.data.ability) + match ability: + "w01", "w02": + if hit_count % 3 == 0 and primary.alive: + primary.apply_effect("root_grasp", "movement_slow", 0.30 if ability == "w02" else 0.20, 3.0 if ability == "w02" else 2.0) + if ability == "w02": + primary.apply_effect("root_grasp_attack", "attack_slow", 0.10, 3.0) + "w05", "w06": + if hit_count % 4 == 0 and primary.alive: + primary.apply_dot("seed_burn", 10.0 if ability == "w06" else 3.0, 4.0, int(unit.data.attack_type)) + "w07", "w08": + if hit_count % 3 == 0: + splash(unit, primary, combatants, 0.80 if ability == "w08" else 0.60, 2.5 if ability == "w08" else 2.0, 4 if ability == "w08" else 3) + "g01", "g02": + if hit_count % 3 == 0 and primary.alive: + primary.apply_dot("burn", 12.0 if ability == "g02" else 4.0, 3.0, int(unit.data.attack_type)) + "g07": splash(unit, primary, combatants, 0.30, 1.5, 3) + "g08": splash(unit, primary, combatants, 0.40, 2.0, 4) + "e05": + if hit_count % 4 == 0: splash(unit, primary, combatants, 0.40, 1.5, 2) + "e07": + if hit_count % 4 == 0: splash(unit, primary, combatants, 0.60, 2.0, 3) + "e10": + if hit_count % 4 == 0: splash(unit, primary, combatants, 0.60, 2.5, 4) + "s04": + if hit_count % 4 == 0: splash(unit, primary, combatants, 0.50, 2.0, 3) + +func splash(unit, primary, combatants: Array, factor: float, radius: float, maximum: int) -> void: + for victim in nearby(unit, combatants, false, primary.position, radius, maximum, primary): + victim.receive_damage(float(unit.data.damage) * factor, int(unit.data.attack_type)) + +func nearby(unit, combatants: Array, allied: bool, center: Vector3, radius: float, maximum: int, excluded = null, health_priority: bool = false) -> Array: + var result: Array = [] + for other in combatants: + if not other.alive or other.team_id != unit.team_id or other == excluded: + continue + if (other.is_attacker == unit.is_attacker) != allied: + continue + if horizontal_distance(other.position, center) <= radius + 0.000001: + result.append(other) + result.sort_custom(func(a, b): + if health_priority and not is_equal_approx(a.hp / a.max_hp, b.hp / b.max_hp): + return a.hp / a.max_hp < b.hp / b.max_hp + var ad = horizontal_distance(a.position, center) + var bd = horizontal_distance(b.position, center) + return a.uid < b.uid if is_equal_approx(ad, bd) else ad < bd + ) + if result.size() > maximum: + result.resize(maximum) + return result + +func horizontal_distance(a: Vector3, b: Vector3) -> float: + return Vector2(a.x, a.z).distance_to(Vector2(b.x, b.z)) diff --git a/scripts/combat/ability_component.gd.uid b/scripts/combat/ability_component.gd.uid new file mode 100644 index 0000000..2f651f9 --- /dev/null +++ b/scripts/combat/ability_component.gd.uid @@ -0,0 +1 @@ +uid://bix73ti8hiq7g diff --git a/scripts/combat/attack_component.gd b/scripts/combat/attack_component.gd new file mode 100644 index 0000000..b5551ea --- /dev/null +++ b/scripts/combat/attack_component.gd @@ -0,0 +1,27 @@ +extends RefCounted +## Only primary attacks advance the hit counter. Extra damage never recurses. + +var progress: float = 0.0 +var hit_count: int = 0 + +func step(unit, combatants: Array, delta: float) -> void: + if not is_instance_valid(unit.target) or not unit.target.alive: + progress = 0.0 + return + if unit.distance_to_unit(unit.target) > float(unit.data.attack_range) + 0.035: + progress = 0.0 + return + progress += delta * unit.attack_speed_factor() + while progress >= 1.0 - 0.000001 and unit.alive and unit.target.alive: + progress = maxf(0.0, progress - 1.0) + hit_count += 1 + var target = unit.target + var damage = float(unit.data.damage) * (1.0 + unit.damage_bonus()) + if hit_count % 4 == 0: + if str(unit.data.ability) == "g05": + damage *= 1.5 + elif str(unit.data.ability) == "g06": + damage *= 1.75 + target.receive_damage(damage, int(unit.data.attack_type)) + unit.play_attack(target.position) + unit.ability_component.on_hit(unit, target, combatants, hit_count) diff --git a/scripts/combat/attack_component.gd.uid b/scripts/combat/attack_component.gd.uid new file mode 100644 index 0000000..7cbf3ee --- /dev/null +++ b/scripts/combat/attack_component.gd.uid @@ -0,0 +1 @@ +uid://1sval3rtge00 diff --git a/scripts/combat/battle_controller.gd b/scripts/combat/battle_controller.gd new file mode 100644 index 0000000..c0b5d32 --- /dev/null +++ b/scripts/combat/battle_controller.gd @@ -0,0 +1,179 @@ +class_name BattleController +extends Node3D +## Pure combat owner: step() returns ledger deltas, never edits match economy. +## WaveManager alone calls step from the fixed physics clock. + +const Unit = preload("res://scripts/combat/unit.gd") +const MAX_COMBAT_TIME: float = 90.0 +const LANE_CENTERS = [-9.0, 9.0] +const SPAWN_COLUMNS = [0.0, -1.5, 1.5, -3.0, 3.0, -4.5, 4.5] + +var render_enabled: bool = true +var units: Array = [] +var elapsed: float = 0.0 +var wave_number: int = 1 +var finished: bool = true +var bounties: Array[int] = [0, 0] +var leaks: Array[int] = [0, 0] +var natural_leaks: Array[int] = [0, 0] +var front_lifetime: Array[float] = [-1.0, -1.0] +var _active: bool = false + +func show_formation(rosters: Array) -> void: + _clear() + _spawn_guardians(rosters) + for unit in units: + unit.refresh_visuals() + finished = true + _active = false + +func begin_battle(rosters: Array, attackers: Array, wave: int) -> void: + _clear() + wave_number = maxi(1, wave) + _spawn_guardians(rosters) + for lane in range(2): + var definitions: Array = attackers[lane] if lane < attackers.size() else [] + var melee: Array = [] + var ranged: Array = [] + for definition in definitions: + var group = melee if float(definition.get("attack_range", 1.0)) <= 1.5 else ranged + if str(definition.get("id", "")) in ["e07", "e08", "e09", "e10"]: + group.push_front(definition) + else: + group.append(definition) + var spawn_index = 0 + var row_offset = 0 + for group in [melee, ranged]: + for index in range(group.size()): + var unit = Unit.new() + add_child(unit) + # Guardian IDs occupy the 0 and 1,000,000 namespaces. + unit.setup(group[index], 2000000 + lane * 100000 + spawn_index, lane, true, Vector2i(-1, -1), 0, render_enabled) + unit.wave_number = wave_number + unit.position = Vector3(float(LANE_CENTERS[lane]) + float(SPAWN_COLUMNS[index % 7]), 0.0, -10.0 - float(row_offset + index / 7) * 1.5) + unit.facing = 0.0 + units.append(unit) + spawn_index += 1 + row_offset += ceili(float(group.size()) / 7.0) + finished = false + _active = true + for lane in range(2): + if not _has_guardians(lane): + front_lifetime[lane] = 0.0 + _refresh_visuals() + +func step(delta: float) -> Dictionary: + var leak_damage: Array[int] = [0, 0] + if not _active or finished: + return _result(leak_damage) + var dt = clampf(delta, 0.0, maxf(0.0, MAX_COMBAT_TIME - elapsed)) + elapsed = minf(MAX_COMBAT_TIME, elapsed + dt) + # One explicit order for every step, including the last step at 90 seconds: + # status expiry/DoT -> ready support -> targets -> movement -> primary+bonus + # attacks -> deaths/line crossings -> simultaneous timeout ledger. + for unit in units: + if unit.alive: + unit.advance_status(dt) + for unit in units: + if unit.alive: + unit.ability_component.step(unit, units, dt) + for unit in units: + if unit.alive: + unit.target = unit.targeting_component.choose(unit, units) + for unit in units: + if unit.alive: + unit.movement_component.step(unit, units, dt, float(LANE_CENTERS[unit.team_id])) + for unit in units: + if unit.alive: + unit.attack_component.step(unit, units, dt) + for unit in units: + if not unit.is_attacker or unit.resolved: + continue + if not unit.alive: + unit.resolved = true + bounties[unit.team_id] += int(unit.data.get("bounty", 0)) + elif unit.position.z >= 16.0: + _resolve_leak(unit, leak_damage) + for lane in range(2): + if front_lifetime[lane] < 0.0 and not _has_guardians(lane): + front_lifetime[lane] = elapsed + if elapsed >= MAX_COMBAT_TIME - 0.000001: + for unit in units: + if unit.is_attacker and unit.alive and not unit.resolved: + _resolve_leak(unit, leak_damage) + finished = true + for unit in units: + if unit.is_attacker and unit.alive: + finished = false + break + if finished: + _active = false + for unit in units: + unit.effects.clear() + unit.dots.clear() + unit.target = null + _refresh_visuals(dt) + return _result(leak_damage) + +func _resolve_leak(unit, leak_damage: Array[int]) -> void: + var damage = ceili(float(unit.data.get("leak_value", 0)) * (1.0 + 0.07 * float(wave_number - 1)) * maxf(0.25, unit.hp / unit.max_hp)) + leak_damage[unit.team_id] += damage + leaks[unit.team_id] += 1 + if str(unit.data.get("id", "")).begins_with("e"): + natural_leaks[unit.team_id] += 1 + unit.resolved = true + unit.leaked = true + unit.alive = false + unit.target = null + +func _result(leak_damage: Array[int]) -> Dictionary: + return { + "finished": finished, + "leak_damage": leak_damage, + "bounties": bounties.duplicate(), + "leaks": leaks.duplicate(), + "natural_leaks": natural_leaks.duplicate(), + "elapsed": elapsed, + "front_lifetime": [elapsed if front_lifetime[0] < 0.0 else front_lifetime[0], elapsed if front_lifetime[1] < 0.0 else front_lifetime[1]], + } + +func _has_guardians(lane: int) -> bool: + for unit in units: + if unit.alive and not unit.is_attacker and unit.team_id == lane: + return true + return false + +func _spawn_guardians(rosters: Array) -> void: + var catalog = get_node("/root/DataCatalog") + for lane in range(mini(2, rosters.size())): + for owned in rosters[lane]: + var definition: Dictionary = catalog.get_unit(str(owned.type_id)) + if definition.is_empty(): + continue + var unit = Unit.new() + add_child(unit) + unit.setup(definition, int(owned.uid), lane, false, owned.cell, int(owned.get("target_policy", 0)), render_enabled) + unit.wave_number = wave_number + unit.position = Vector3(float(LANE_CENTERS[lane]) - 5.0 + float(owned.cell.x) * 2.0, 0.0, -7.0 + float(owned.cell.y) * 2.0) + units.append(unit) + +func _clear() -> void: + for unit in units: + unit.free() + units.clear() + elapsed = 0.0 + bounties = [0, 0] + leaks = [0, 0] + natural_leaks = [0, 0] + front_lifetime = [-1.0, -1.0] + _active = false + finished = true + +func _refresh_visuals(delta: float = 0.0) -> void: + if render_enabled: + for unit in units: + unit.refresh_visuals(delta) + +func _process(delta: float) -> void: + if render_enabled and finished and not GameState.paused: + _refresh_visuals(minf(delta,.1)) diff --git a/scripts/combat/battle_controller.gd.uid b/scripts/combat/battle_controller.gd.uid new file mode 100644 index 0000000..a3b6c1b --- /dev/null +++ b/scripts/combat/battle_controller.gd.uid @@ -0,0 +1 @@ +uid://bqs1lu54ovnug diff --git a/scripts/combat/movement_component.gd b/scripts/combat/movement_component.gd new file mode 100644 index 0000000..8f49be7 --- /dev/null +++ b/scripts/combat/movement_component.gd @@ -0,0 +1,37 @@ +extends RefCounted +## Ground movement with lightweight separation, without navigation dependencies. + +func step(unit, combatants: Array, delta: float, lane_center: float) -> void: + var heading = Vector3.ZERO + var travel_limit = INF + if is_instance_valid(unit.target) and unit.target.alive: + var offset: Vector3 = unit.target.position - unit.position + offset.y = 0.0 + var gap = offset.length() + if gap > float(unit.data.attack_range): + heading = offset.normalized() + travel_limit = maxf(0.0, gap - float(unit.data.attack_range) + 0.02) + elif unit.is_attacker: + heading = Vector3.BACK + var separation = Vector3.ZERO + for other in combatants: + if other == unit or not other.alive or other.team_id != unit.team_id: + continue + var offset: Vector3 = unit.position - other.position + offset.y = 0.0 + var distance = offset.length() + # Space allies according to the visible stone bodies. Opponents can still + # enter the shortest melee range (1.0 m); separation must not prevent hits. + var spacing: float = 1.30 if other.is_attacker == unit.is_attacker else .90 + if distance < spacing: + if distance < 0.0001: + offset = Vector3.RIGHT if unit.uid < other.uid else Vector3.LEFT + distance = 0.001 + separation += offset.normalized() * (spacing - distance) * 2.0 + var displacement = heading * minf(float(unit.data.speed) * unit.movement_factor() * delta, travel_limit) + displacement += separation.limit_length(0.9) * delta + unit.position += displacement + unit.position.x = clampf(unit.position.x, lane_center - 5.6, lane_center + 5.6) + unit.position.z = clampf(unit.position.z, -20.0, 16.1) + if heading.length_squared() > 0.001: + unit.facing = atan2(heading.x, heading.z) diff --git a/scripts/combat/movement_component.gd.uid b/scripts/combat/movement_component.gd.uid new file mode 100644 index 0000000..34e5e0d --- /dev/null +++ b/scripts/combat/movement_component.gd.uid @@ -0,0 +1 @@ +uid://bl1l7p8tk7dwj diff --git a/scripts/combat/targeting_component.gd b/scripts/combat/targeting_component.gd new file mode 100644 index 0000000..87e2981 --- /dev/null +++ b/scripts/combat/targeting_component.gd @@ -0,0 +1,32 @@ +extends RefCounted +## Retains a living target, then applies the public formation target policy. + +func choose(unit, combatants: Array): + if is_instance_valid(unit.target) and unit.target.alive: + if unit.distance_to_unit(unit.target) <= 10.0: + return unit.target + var candidates: Array = [] + var nearby: Array = [] + for other in combatants: + if not other.alive or other.team_id != unit.team_id or other.is_attacker == unit.is_attacker: + continue + candidates.append(other) + if unit.distance_to_unit(other) <= 8.0: + nearby.append(other) + if candidates.is_empty(): + return null + var policy = 0 if unit.is_attacker or nearby.is_empty() else unit.target_policy + if not nearby.is_empty(): + candidates = nearby + candidates.sort_custom(func(a, b): + var av = unit.distance_to_unit(a) + var bv = unit.distance_to_unit(b) + if policy == 1: + av = a.hp + bv = b.hp + elif policy == 2: + av = -a.max_hp + bv = -b.max_hp + return a.uid < b.uid if is_equal_approx(av, bv) else av < bv + ) + return candidates[0] diff --git a/scripts/combat/targeting_component.gd.uid b/scripts/combat/targeting_component.gd.uid new file mode 100644 index 0000000..2f4f283 --- /dev/null +++ b/scripts/combat/targeting_component.gd.uid @@ -0,0 +1 @@ +uid://cujh72bkv58nu diff --git a/scripts/combat/unit.gd b/scripts/combat/unit.gd new file mode 100644 index 0000000..865b3ba --- /dev/null +++ b/scripts/combat/unit.gd @@ -0,0 +1,433 @@ +class_name CombatUnit +extends Node3D +## A disposable battle instance. Ownership remains in EconomyManager's roster. + +const MovementComponent = preload("res://scripts/combat/movement_component.gd") +const TargetingComponent = preload("res://scripts/combat/targeting_component.gd") +const AttackComponent = preload("res://scripts/combat/attack_component.gd") +const AbilityComponent = preload("res://scripts/combat/ability_component.gd") +const EnemyVisuals = preload("res://scripts/presentation/enemy_visuals.gd") + +const DAMAGE_MATRIX = [[1.30, 0.75, 1.00], [1.00, 1.30, 0.75], [0.75, 1.00, 1.30]] + +var uid: int = 0 +var team_id: int = 0 +var is_attacker: bool = false +var alive: bool = true +var hp: float = 1.0 +var max_hp: float = 1.0 +var data: Dictionary = {} +var home_cell: Vector2i = Vector2i(-1, -1) +var target_policy: int = 0 +var target = null +var shield: float = 0.0 +var shield_remaining: float = INF +var effects: Dictionary = {} +var dots: Dictionary = {} +var combat_time: float = 0.0 +var wave_number: int = 1 +var resolved: bool = false +var leaked: bool = false +var facing: float = PI +var attack_flash: float = 0.0 +var ability_flash: float = 0.0 +var ability_pose_flash: float = 0.0 +var movement_component = MovementComponent.new() +var targeting_component = TargetingComponent.new() +var attack_component = AttackComponent.new() +var ability_component = AbilityComponent.new() + +var _body: Node3D +var _hp_bar: MeshInstance3D +var _shield_bar: MeshInstance3D +var _selection: MeshInstance3D +var _body_material: StandardMaterial3D +var _base_color: Color +var _shot: MeshInstance3D +var _pulse: MeshInstance3D +var _burn: MeshInstance3D +var _shot_target: Vector3 +var _previous_position: Vector3 +var model_loaded: bool = false +var visual_height: float = 1.6 +var _model: Node3D +var _bars: Node3D +var hit_flash: float = 0.0 +var _pose_attack: float = 0.0 + +func setup(definition: Dictionary, stable_id: int, lane: int, attacker: bool, cell: Vector2i = Vector2i(-1, -1), policy: int = 0, make_visuals: bool = true) -> void: + data = definition.duplicate(true) + uid = stable_id + team_id = lane + is_attacker = attacker + home_cell = cell + target_policy = policy + max_hp = float(data.get("max_hp", 1.0)) + hp = max_hp + alive = true + target = null + shield = 0.0 + shield_remaining = INF + effects.clear() + dots.clear() + combat_time = 0.0 + resolved = false + leaked = false + attack_component = AttackComponent.new() + ability_component = AbilityComponent.new() + for child in get_children(): + child.free() + _body = null + _hp_bar = null + _shield_bar = null + _selection = null + _body_material = null + model_loaded = false + _model = null + _bars = null + hit_flash = 0.0 + _pose_attack = 0.0 + attack_flash = 0.0 + ability_flash = 0.0 + ability_pose_flash = 0.0 + if make_visuals: + _make_visuals() + ability_component.start(self) + +func distance_to_unit(other) -> float: + return Vector2(position.x, position.z).distance_to(Vector2(other.position.x, other.position.z)) + +func receive_damage(raw: float, attack_type: int) -> void: + if not alive: + return + var armor = clampi(int(data.get("armor_type", 0)), 0, 2) + var value = maxf(0.0, raw) * float(DAMAGE_MATRIX[clampi(attack_type, 0, 2)][armor]) + value *= 1.0 - damage_reduction() + var absorbed = minf(shield, value) + shield -= absorbed + hp = maxf(0.0, hp - (value - absorbed)) + if value > 0.0: + hit_flash = .18 + if hp <= 0.0: + alive = false + target = null + +func heal(amount: float) -> void: + if alive: + hp = minf(max_hp, hp + maxf(0.0, amount) * (1.0 - strongest_effect("healing_reduction"))) + +func grant_shield(amount: float, duration: float = INF) -> void: + if alive and amount > shield: + shield = amount + shield_remaining = duration + +func apply_effect(family: String, kind: String, amount: float, duration: float) -> void: + if not alive: + return + if effects.has(family): + effects[family].amount = maxf(float(effects[family].amount), amount) + effects[family].remaining = maxf(float(effects[family].remaining), duration) + else: + effects[family] = {"kind": kind, "amount": amount, "remaining": duration} + +func apply_dot(family: String, damage: float, duration: float, attack_type: int) -> void: + if not alive: + return + if dots.has(family): + var effect: Dictionary = dots[family] + if damage > float(effect.damage): + effect.damage = damage + effect.attack_type = attack_type + effect.remaining = maxf(float(effect.remaining), duration) + else: + dots[family] = {"damage": damage, "remaining": duration, "next_tick": 1.0, "attack_type": attack_type} + +func advance_status(delta: float) -> void: + combat_time += delta + attack_flash = maxf(0.0, attack_flash - delta) + _pose_attack = maxf(0.0, _pose_attack - delta) + hit_flash = maxf(0.0, hit_flash - delta) + ability_flash = maxf(0.0, ability_flash - delta) + ability_pose_flash = maxf(0.0, ability_pose_flash - delta) + for family in effects.keys(): + effects[family].remaining -= delta + if float(effects[family].remaining) <= 0.000001: + effects.erase(family) + if shield_remaining != INF: + shield_remaining -= delta + if shield_remaining <= 0.000001: + shield = 0.0 + for family in dots.keys(): + var effect: Dictionary = dots[family] + effect.next_tick -= minf(delta, maxf(0.0, float(effect.remaining))) + while float(effect.next_tick) <= 0.000001 and alive: + receive_damage(float(effect.damage), int(effect.attack_type)) + effect.next_tick += 1.0 + effect.remaining -= delta + if float(effect.remaining) <= 0.000001: + dots.erase(family) + +func strongest_effect(kind: String) -> float: + var amount = 0.0 + for effect in effects.values(): + if str(effect.kind) == kind: + amount = maxf(amount, float(effect.amount)) + return amount + +func damage_bonus() -> float: + var result = 0.0 + for effect in effects.values(): + if str(effect.kind) == "damage": + result += float(effect.amount) + return minf(0.30, result) + +func damage_reduction() -> float: + var result = strongest_effect("reduction") + match str(data.get("ability", "")): + "g03": + if combat_time < 8.0 - 0.000001: + result = maxf(result, 0.15) + "g04": result = maxf(result, 0.25 if combat_time < 10.0 - 0.000001 else 0.10) + return minf(0.35, result) + +func attack_speed_factor() -> float: + var slowing = strongest_effect("attack_slow") * (0.5 if _is_boss() else 1.0) + return 1.0 + clampf(strongest_effect("attack_speed") - slowing, -0.25, 0.25) + +func movement_factor() -> float: + return 1.0 - minf(0.35, strongest_effect("movement_slow") * (0.5 if _is_boss() else 1.0)) + +func _is_boss() -> bool: + return str(data.get("id", "")) in ["e07", "e08", "e09", "e10"] + +func set_selected(selected: bool) -> void: + if is_instance_valid(_selection): + _selection.visible = selected + +func play_ability() -> void: + # A received heal shares the effect pulse, but never casts this unit's ability. + ability_flash = 0.5 + ability_pose_flash = 0.5 + if model_loaded: + Soundscape.play("ability", team_id, true) + +func play_attack(at: Vector3) -> void: + attack_flash = 0.18 + _pose_attack = .28 + if model_loaded: + var sound: String = "stone" + if str(data.id) in ["g07", "g08"]: + sound = "mortar" + elif float(data.get("attack_range", 1.0)) > 1.5: + sound = "bolt" if int(data.get("attack_type", 0)) == 1 else "ember" + Soundscape.play(sound, team_id, true, .94 + (uid % 5) * .03) + _shot_target = at + Vector3.UP * .75 + var heading: Vector3 = at - position + facing = atan2(heading.x, heading.z) + +func refresh_visuals(delta: float = 0.0) -> void: + var skeletal: bool = is_instance_valid(_model) and _model.has_method("update_combat") + visible = alive or (skeletal and not leaked) + if not is_instance_valid(_body): + return + if skeletal: + _body.rotation.y = facing + var distance: float = position.distance_to(_previous_position) if delta > 0 else 0.0 + var in_range: bool = alive and is_instance_valid(target) and distance_to_unit(target) <= float(data.attack_range)+.035 + _model.update_combat(delta,distance,in_range,attack_component.progress,attack_component.hit_count,ability_pose_flash,hit_flash,alive) + _previous_position = position + _bars.visible = alive + if not alive: + _selection.hide() + _shot.hide() + _pulse.hide() + _burn.hide() + return + if not alive: + return + _body.rotation.y = facing + var moving: bool = position.distance_squared_to(_previous_position) > 0.00001 + _body.position.y = sin(_pose_attack / .28 * PI) * .025 + _body.rotation.x = -sin(_pose_attack / .28 * PI) * .05 + if not skeletal and is_instance_valid(_model) and _model.has_method("pose"): + _model.pose(combat_time + (uid % 17) * .23, moving, _pose_attack, ability_pose_flash, hit_flash) + if moving and not skeletal: + _body.position.y += absf(sin(combat_time * 10.0 + uid)) * .035 + if skeletal: + _body.position.y = 0 + _body.rotation.x = 0 + _previous_position = position + _hp_bar.scale.x = maxf(0.001, hp / max_hp) + _hp_bar.position.x = -0.44 * (1.0 - hp / max_hp) + _shield_bar.visible = shield > 0.0 + _shield_bar.scale.x = clampf(shield / max_hp, 0.001, 1.0) + if _body_material != null: + _body_material.emission_enabled = ability_flash > 0.0 + _body_material.emission = _base_color * 0.5 + _shot.visible = attack_flash > 0.0 and float(data.get("attack_range", 1.0)) > 1.5 + if _shot.visible: + var progress: float = 1.0 - attack_flash / .18 + var offset: Vector3 = _shot_target - position + _shot.position = Vector3(0, visual_height * .6, 0).lerp(offset, progress) + if str(data.id) in ["g07", "g08"]: + _shot.position.y += sin(progress * PI) * 1.1 + _shot.scale = Vector3.ONE * (1.3 if str(data.id) == "g08" else 1.0) + _pulse.visible = ability_flash > 0.0 + if _pulse.visible: + var radius: float = 1.0 + (1.0 - ability_flash / .5) * 3.0 + _pulse.scale = Vector3(radius, 1.0, radius) + (_pulse.material_override as StandardMaterial3D).albedo_color.a = ability_flash * 1.5 + _burn.visible = dots.has("burn") or dots.has("seed_burn") + if _burn.visible: + (_burn.material_override as StandardMaterial3D).albedo_color = Color("a7d277") if dots.has("seed_burn") and not dots.has("burn") else Color("ffad50") + _burn.position.y = visual_height * .65 + sin(combat_time * 16.0) * .12 + +func _make_visuals() -> void: + _body = Node3D.new() + _body.name = "VisualBody" + add_child(_body) + var id: String = str(data.get("id", "")) + var model: Node3D = AssetLibrary.instantiate_fighter(id) + if model == null and is_attacker: + model = EnemyVisuals.create(data) + if model != null: + _body.add_child(model) + model_loaded = true + _model = model + visual_height = model.get_aabb().end.y + else: + _make_fallback_body() + visual_height = 2.3 if _is_boss() else 1.6 + var ring := TorusMesh.new() + ring.inner_radius = .48 + ring.outer_radius = .58 + ring.rings = 16 if team_id == 0 else 3 + ring.ring_segments = 4 + var team_color := Color("57d4c6") if team_id == 0 else Color("f18c84") + if is_attacker: + team_color = Color("d96d8a") + _add_mesh(self, ring, _glow_material(team_color), Vector3(0, .055, 0)) + var selection_mesh := TorusMesh.new() + selection_mesh.inner_radius = .70 + selection_mesh.outer_radius = .80 + selection_mesh.rings = 32 + selection_mesh.ring_segments = 4 + _selection = _add_mesh(self, selection_mesh, _glow_material(Color("ffe6a0"), 2.4), Vector3(0,.075,0)) + _selection.visible = false + _bars = Node3D.new() + _bars.name = "HealthBillboard" + _bars.position.y = visual_height + .22 + add_child(_bars) + var bar_background := BoxMesh.new() + bar_background.size = Vector3(.98,.10,.012) + _add_mesh(_bars, bar_background, _bar_material(Color("0c141c")), Vector3.ZERO) + var health_mesh := BoxMesh.new() + health_mesh.size = Vector3(.92,.055,.015) + _hp_bar = _add_mesh(_bars,health_mesh,_bar_material(Color("f07878") if is_attacker else Color("6ee0a8")),Vector3(0,0,.012)) + _shield_bar = _add_mesh(_bars,health_mesh,_bar_material(Color("7ec8ff")),Vector3(0,.11,.012)) + _shield_bar.visible = false + var spark_mesh := SphereMesh.new() + spark_mesh.radius = .10 + spark_mesh.height = .20 + spark_mesh.radial_segments = 6 + spark_mesh.rings = 2 + var nature: bool = id.begins_with("w") + var ember := _material((Color("d99db8") if id in ["w07","w08"] else Color("a7d277")) if nature else (Color("ffad50") if not is_attacker else Color("eb8299"))) + ember.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + _shot = _add_mesh(self,spark_mesh,ember,Vector3.ZERO) + _shot.visible = false + _burn = _add_mesh(self,spark_mesh,ember.duplicate(),Vector3.ZERO) + _burn.scale = Vector3(1.5,3,1.5) + _burn.visible = false + var aura := TorusMesh.new() + aura.inner_radius = .90 + aura.outer_radius = 1.0 + aura.rings = 32 + aura.ring_segments = 4 + var aura_material := _material(Color("78dcad") if nature else Color("ffcf7c")) + aura_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + aura_material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + _pulse = _add_mesh(self,aura,aura_material,Vector3(0,.08,0)) + _pulse.visible = false + if _is_boss(): + var nameplate := Label3D.new() + nameplate.text = str(data.display_name).to_upper() + nameplate.font_size = 32 + nameplate.pixel_size = .008 + nameplate.position.y = visual_height + .60 + nameplate.billboard = BaseMaterial3D.BILLBOARD_ENABLED + nameplate.modulate = Color("ffb9a4") + add_child(nameplate) + refresh_visuals() + +func _make_fallback_body() -> void: + var armor = int(data.get("armor_type", 0)) + var upgraded = not is_attacker and str(data.get("id", "")).right(1) in ["2", "4", "6", "8", "0"] + _base_color = Color("e6663d") if not is_attacker else Color("d7d8e0") + if armor == 1: + _base_color = Color("676273") if not is_attacker else Color("98a3b7") + elif armor == 2: + _base_color = Color("efbb68") if not is_attacker else Color("b49dde") + _body_material = _material(_base_color) + var body_mesh: Mesh + if armor == 1: + var box = BoxMesh.new() + box.size = Vector3(0.65, 0.9, 0.58) + body_mesh = box + else: + var cylinder = CylinderMesh.new() + cylinder.top_radius = 0.22 if armor == 2 else 0.32 + cylinder.bottom_radius = 0.40 + cylinder.height = 0.90 + cylinder.radial_segments = 5 if armor == 2 else 6 + body_mesh = cylinder + _add_mesh(_body, body_mesh, _body_material, Vector3(0, 0.70, 0)) + var head = SphereMesh.new() + head.radius = 0.23 + head.height = 0.46 + head.radial_segments = 8 + head.rings = 4 + _add_mesh(_body, head, _material(Color("ffe0a1") if not is_attacker else Color("535575")), Vector3(0, 1.31, 0)) + var weapon = BoxMesh.new() + weapon.size = Vector3(0.12, 0.14, 0.9) if float(data.get("attack_range", 1.0)) > 1.5 else Vector3(0.13, 0.95, 0.13) + _add_mesh(_body, weapon, _material(Color("e6be77")), Vector3(0.43, 0.90, 0.12)) + if upgraded or _is_boss(): + var crest = CylinderMesh.new() + crest.top_radius = 0.0 + crest.bottom_radius = 0.29 + crest.height = 0.42 + crest.radial_segments = 4 + _add_mesh(_body, crest, _material(Color("ffc861")), Vector3(0, 1.65, 0)) + if _is_boss(): + _body.scale = Vector3.ONE * 1.35 + +func _material(color: Color) -> StandardMaterial3D: + var material = StandardMaterial3D.new() + material.albedo_color = color + material.roughness = 0.95 + return material + +func _add_mesh(parent: Node3D, mesh: Mesh, material: StandardMaterial3D, at: Vector3) -> MeshInstance3D: + var instance = MeshInstance3D.new() + instance.mesh = mesh + instance.material_override = material + instance.position = at + parent.add_child(instance) + return instance + +func face_health_bars(camera_basis: Basis) -> void: + if is_instance_valid(_bars): + _bars.global_basis = camera_basis + +func _bar_material(color: Color) -> StandardMaterial3D: + var mat: StandardMaterial3D = _material(color) + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + return mat + +func _glow_material(color: Color, energy: float = 1.6) -> StandardMaterial3D: + var mat: StandardMaterial3D = _material(color) + mat.emission_enabled = true + mat.emission = color + mat.emission_energy_multiplier = energy + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + return mat diff --git a/scripts/combat/unit.gd.uid b/scripts/combat/unit.gd.uid new file mode 100644 index 0000000..10560ce --- /dev/null +++ b/scripts/combat/unit.gd.uid @@ -0,0 +1 @@ +uid://3nji6a7fg40u diff --git a/scripts/data/data_catalog.gd b/scripts/data/data_catalog.gd new file mode 100644 index 0000000..3c81c67 --- /dev/null +++ b/scripts/data/data_catalog.gd @@ -0,0 +1,184 @@ +extends Node +## Immutable design data. Callers receive fresh combat dictionaries. + +const SHORT_WAVE_COUNT: int = 8 +const EXPEDITION_WAVE_COUNT: int = 20 +const BASE_IDS: Array[String] = ["g01", "g03", "g05", "g07", "g09"] +const DAMAGE_NAMES: Array[String] = ["Klinge", "Durchschlag", "Impuls"] +const ARMOR_NAMES: Array[String] = ["Leicht", "Schwer", "Ätherisch"] +const UNITS: Dictionary = { + "g01": {"id": "g01", "display_name": "Kohlenbeißer", "cost": 45, "upgrade_id": "g02", "max_hp": 260.0, "damage": 17.0, "attack_type": 0, "armor_type": 0, "attack_range": 1.1, "speed": 2.4, "ability": "g01", "leak_value": 0, "bounty": 0, "color": Color("d76e36"), "ability_description": "Jeder 3. Treffer: Brand, 4 Schaden/s für 3 s."}, + "g02": {"id": "g02", "display_name": "Schlackenklaue", "cost": 90, "upgrade_id": "", "max_hp": 690.0, "damage": 44.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.2, "speed": 2.4, "ability": "g02", "leak_value": 0, "bounty": 0, "color": Color("ef9849"), "ability_description": "Jeder 3. Treffer: Brand, 12 Schaden/s für 3 s."}, + "g03": {"id": "g03", "display_name": "Schlackenwacht", "cost": 70, "upgrade_id": "g04", "max_hp": 650.0, "damage": 11.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.2, "speed": 2.4, "ability": "g03", "leak_value": 0, "bounty": 0, "color": Color("8c5544"), "ability_description": "Erste 8 s: 15 % weniger erlittener Schaden."}, + "g04": {"id": "g04", "display_name": "Basaltbastion", "cost": 150, "upgrade_id": "", "max_hp": 1650.0, "damage": 27.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.4, "speed": 2.4, "ability": "g04", "leak_value": 0, "bounty": 0, "color": Color("ba6c42"), "ability_description": "Erste 10 s: 25 % weniger Schaden, danach 10 %."}, + "g05": {"id": "g05", "display_name": "Funkenlanze", "cost": 65, "upgrade_id": "g06", "max_hp": 240.0, "damage": 24.0, "attack_type": 1, "armor_type": 0, "attack_range": 5.5, "speed": 2.0, "ability": "g05", "leak_value": 0, "bounty": 0, "color": Color("edb354"), "ability_description": "Jeder 4. Treffer: 50 % zusätzlicher Grundschaden."}, + "g06": {"id": "g06", "display_name": "Glasballiste", "cost": 140, "upgrade_id": "", "max_hp": 640.0, "damage": 65.0, "attack_type": 1, "armor_type": 0, "attack_range": 6.5, "speed": 2.0, "ability": "g06", "leak_value": 0, "bounty": 0, "color": Color("ffd579"), "ability_description": "Jeder 4. Treffer: 75 % zusätzlicher Grundschaden."}, + "g07": {"id": "g07", "display_name": "Aschenwerfer", "cost": 95, "upgrade_id": "g08", "max_hp": 310.0, "damage": 23.0, "attack_type": 2, "armor_type": 0, "attack_range": 4.5, "speed": 2.0, "ability": "g07", "leak_value": 0, "bounty": 0, "color": Color("cb7867"), "ability_description": "Jeder Treffer: 30 % Flächenschaden an bis zu 3 weiteren Zielen in 1,5 m."}, + "g08": {"id": "g08", "display_name": "Kraterrufer", "cost": 190, "upgrade_id": "", "max_hp": 820.0, "damage": 58.0, "attack_type": 2, "armor_type": 1, "attack_range": 5.0, "speed": 2.0, "ability": "g08", "leak_value": 0, "bounty": 0, "color": Color("f6956e"), "ability_description": "Jeder Treffer: 40 % Flächenschaden an bis zu 4 weiteren Zielen in 2 m."}, + "g09": {"id": "g09", "display_name": "Herdhüter", "cost": 85, "upgrade_id": "g10", "max_hp": 420.0, "damage": 12.0, "attack_type": 2, "armor_type": 2, "attack_range": 3.5, "speed": 2.0, "ability": "g09", "leak_value": 0, "bounty": 0, "color": Color("e9ae80"), "ability_description": "Alle 6 s: bis zu 3 Verbündete in 3 m erhalten für 4 s +10 % Grundangriffsschaden."}, + "g10": {"id": "g10", "display_name": "Sonnenesse", "cost": 170, "upgrade_id": "", "max_hp": 1080.0, "damage": 30.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.0, "speed": 2.0, "ability": "g10", "leak_value": 0, "bounty": 0, "color": Color("ffe0a4"), "ability_description": "Alle 6 s: bis zu 4 Verbündete in 4 m erhalten für 4 s +15 % Grundangriffsschaden und 45 Heilung."}, + "w01": {"id": "w01", "display_name": "Dornhopser", "cost": 50, "upgrade_id": "w02", "max_hp": 290.0, "damage": 18.0, "attack_type": 0, "armor_type": 0, "attack_range": 1.1, "speed": 2.4, "ability": "w01", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 3. Treffer: −20 % Bewegung für 2 s.", "color": Color("a7ba6c")}, + "w02": {"id": "w02", "display_name": "Rankenschnapper", "cost": 100, "upgrade_id": "", "max_hp": 800.0, "damage": 47.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.3, "speed": 2.4, "ability": "w02", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 3. Treffer: −30 % Bewegung und −10 % Angriffstempo für 3 s.", "color": Color("a7ba6c")}, + "w03": {"id": "w03", "display_name": "Korkrücken", "cost": 75, "upgrade_id": "w04", "max_hp": 620.0, "damage": 12.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.2, "speed": 2.4, "ability": "w03", "leak_value": 0, "bounty": 0, "ability_description": "Heilt sich alle 5 s um 35 HP, sobald er verwundet ist.", "color": Color("a7ba6c")}, + "w04": {"id": "w04", "display_name": "Ringborke", "cost": 155, "upgrade_id": "", "max_hp": 1560.0, "damage": 31.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.4, "speed": 2.4, "ability": "w04", "leak_value": 0, "bounty": 0, "ability_description": "Heilt sich alle 5 s um 100 HP, sobald er verwundet ist.", "color": Color("a7ba6c")}, + "w05": {"id": "w05", "display_name": "Samenschleuder", "cost": 60, "upgrade_id": "w06", "max_hp": 230.0, "damage": 23.0, "attack_type": 1, "armor_type": 0, "attack_range": 5.5, "speed": 2.0, "ability": "w05", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 4. Treffer: Keimbrand, 3 Schaden/s für 4 s.", "color": Color("a7ba6c")}, + "w06": {"id": "w06", "display_name": "Zapfenkrone", "cost": 135, "upgrade_id": "", "max_hp": 630.0, "damage": 61.0, "attack_type": 1, "armor_type": 0, "attack_range": 6.0, "speed": 2.0, "ability": "w06", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 4. Treffer: Keimbrand, 10 Schaden/s für 4 s.", "color": Color("a7ba6c")}, + "w07": {"id": "w07", "display_name": "Sporenkelch", "cost": 100, "upgrade_id": "w08", "max_hp": 370.0, "damage": 22.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.0, "speed": 2.0, "ability": "w07", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 3. Treffer: 60 % Grundschaden an bis zu 3 weiteren Zielen in 2 m.", "color": Color("a7ba6c")}, + "w08": {"id": "w08", "display_name": "Pilzkathedrale", "cost": 195, "upgrade_id": "", "max_hp": 940.0, "damage": 59.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.5, "speed": 2.0, "ability": "w08", "leak_value": 0, "bounty": 0, "ability_description": "Jeder 3. Treffer: 80 % Grundschaden an bis zu 4 weiteren Zielen in 2,5 m.", "color": Color("a7ba6c")}, + "w09": {"id": "w09", "display_name": "Tauhüter", "cost": 90, "upgrade_id": "w10", "max_hp": 390.0, "damage": 10.0, "attack_type": 2, "armor_type": 0, "attack_range": 4.0, "speed": 2.0, "ability": "w09", "leak_value": 0, "bounty": 0, "ability_description": "Alle 4 s: heilt den am stärksten verwundeten Verbündeten in 4 m um 65 HP.", "color": Color("a7ba6c")}, + "w10": {"id": "w10", "display_name": "Quellgeflecht", "cost": 180, "upgrade_id": "", "max_hp": 1000.0, "damage": 27.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.5, "speed": 2.0, "ability": "w10", "leak_value": 0, "bounty": 0, "ability_description": "Alle 4 s: heilt bis zu 3 verwundete Verbündete in 4,5 m um je 80 HP.", "color": Color("a7ba6c")}, +} +const ENEMIES: Dictionary = { + "e01": {"id": "e01", "display_name": "Splitterling", "max_hp": 90.0, "damage": 6.0, "attack_type": 0, "armor_type": 0, "attack_range": 1.0, "speed": 3.0, "ability": "e01", "leak_value": 25, "bounty": 3}, + "e02": {"id": "e02", "display_name": "Schalenläufer", "max_hp": 240.0, "damage": 9.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.2, "speed": 2.0, "ability": "e02", "leak_value": 55, "bounty": 6}, + "e03": {"id": "e03", "display_name": "Nebelrest", "max_hp": 150.0, "damage": 11.0, "attack_type": 2, "armor_type": 2, "attack_range": 3.5, "speed": 2.2, "ability": "e03", "leak_value": 40, "bounty": 5}, + "e04": {"id": "e04", "display_name": "Fadenschütze", "max_hp": 130.0, "damage": 12.0, "attack_type": 1, "armor_type": 0, "attack_range": 6.0, "speed": 2.4, "ability": "e04", "leak_value": 35, "bounty": 5}, + "e05": {"id": "e05", "display_name": "Bruchstampfer", "max_hp": 480.0, "damage": 16.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.4, "speed": 1.6, "ability": "e05", "leak_value": 90, "bounty": 10}, + "e06": {"id": "e06", "display_name": "Knotenrufer", "max_hp": 190.0, "damage": 7.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.0, "speed": 2.0, "ability": "e06", "leak_value": 45, "bounty": 6}, + "e07": {"id": "e07", "display_name": "Bruchhirsch", "max_hp": 1100.0, "damage": 28.0, "attack_type": 0, "armor_type": 0, "attack_range": 1.4, "speed": 1.8, "ability": "e07", "leak_value": 250, "bounty": 30, "is_boss": true}, + "e08": {"id": "e08", "display_name": "Riegelkoloss", "max_hp": 1400.0, "damage": 30.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.5, "speed": 1.5, "ability": "e08", "leak_value": 330, "bounty": 40, "is_boss": true}, + "e09": {"id": "e09", "display_name": "Maskenrichter", "max_hp": 1800.0, "damage": 34.0, "attack_type": 2, "armor_type": 2, "attack_range": 5.0, "speed": 1.8, "ability": "e09", "leak_value": 400, "bounty": 50, "is_boss": true}, + "e10": {"id": "e10", "display_name": "Schlundkrone", "max_hp": 3000.0, "damage": 50.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.5, "speed": 1.3, "ability": "e10", "leak_value": 600, "bounty": 70, "is_boss": true}, +} +const SENDS: Dictionary = { + "s01": {"id": "s01", "display_name": "Nadelspäher", "cost": 20, "income_gain": 3, "max_hp": 100.0, "damage": 8.0, "attack_type": 1, "armor_type": 0, "attack_range": 4.5, "speed": 2.8, "ability": "s01", "leak_value": 30, "bounty": 3}, + "s02": {"id": "s02", "display_name": "Rostschieber", "cost": 40, "income_gain": 5, "max_hp": 240.0, "damage": 8.0, "attack_type": 0, "armor_type": 1, "attack_range": 1.2, "speed": 1.8, "ability": "s02", "leak_value": 55, "bounty": 6}, + "s03": {"id": "s03", "display_name": "Dunstsänger", "cost": 80, "income_gain": 9, "max_hp": 320.0, "damage": 10.0, "attack_type": 2, "armor_type": 2, "attack_range": 5.0, "speed": 2.0, "ability": "s03", "leak_value": 70, "bounty": 9}, + "s04": {"id": "s04", "display_name": "Keilbrecher", "cost": 130, "income_gain": 12, "max_hp": 650.0, "damage": 20.0, "attack_type": 1, "armor_type": 1, "attack_range": 1.3, "speed": 1.6, "ability": "s04", "leak_value": 120, "bounty": 14}, + "s05": {"id": "s05", "display_name": "Risszehrer", "cost": 200, "income_gain": 17, "max_hp": 1000.0, "damage": 30.0, "attack_type": 2, "armor_type": 2, "attack_range": 4.0, "speed": 1.7, "ability": "s05", "leak_value": 180, "bounty": 20}, +} +# Glutpakt vertical slice: a readable eight-wave progression with two bosses. +const WAVES: Array[Dictionary] = [ + {"e01": 8}, {"e01": 10}, {"e01": 6, "e02": 4}, + {"e01": 8, "e04": 4}, {"e07": 1, "e01": 6}, + {"e02": 6, "e01": 6}, {"e03": 8, "e01": 4}, + {"e08": 1, "e02": 2, "e04": 3}, +] +const WAVE_TITLES: Array[String] = [ + "Erste Risse", "Splitterstrom", "Harte Schalen", "Fäden im Rücken", + "Der Bruchhirsch", "Gepanzerter Vorstoß", "Stimmen aus dem Nebel", "Der letzte Riegel" +] +const WAVE_HINTS: Array[String] = [ + "Stelle Schlackenwacht und Kohlenbeißer nach vorn, die Funkenlanze dahinter.", + "Ergänze deine Verteidigung. Arbeiter produzieren erst ab der nächsten Bauphase.", + "Durchschlag wirkt gegen schwere Schalen. Söldner sind jetzt verfügbar.", + "Schützen stehen hinten. Flächenschaden hilft gegen die Splitterlinge davor.", + "BOSS · Der Bruchhirsch trifft bei jedem vierten Angriff mehrere Ziele. Werte deine Front auf.", + "Schwere Rüstung: Funkenlanze und Glasballiste verursachen 30 % mehr Schaden.", + "Ätherische Gegner: Aschenwerfer und Herdhüter nutzen Impulsschaden. Halte die Gruppe zusammen.", + "FINALE · Riegelkoloss mit Startschutz. Starke Front, Durchschlag und alle übrigen Funken einsetzen." +] + +# Full expedition from the design dossier; the proven short match stays separate. +const EXPEDITION_WAVES: Array[Dictionary] = [ + {"e01":8}, {"e01":10}, {"e01":6,"e02":4}, {"e01":8,"e04":4}, + {"e07":1,"e01":6}, {"e02":6,"e01":6}, {"e03":8,"e01":4}, + {"e02":6,"e04":6,"e01":4}, {"e05":4,"e02":6,"e06":4}, + {"e08":1,"e03":8,"e04":4}, {"e01":16,"e04":6}, + {"e02":8,"e05":4,"e06":4}, {"e03":12,"e04":6}, + {"e05":6,"e02":6,"e01":6}, {"e09":1,"e03":6,"e06":4}, + {"e01":18,"e04":6,"e03":4}, {"e05":8,"e02":6,"e06":4}, + {"e03":10,"e04":8,"e06":4}, {"e05":6,"e02":8,"e01":8,"e04":4}, + {"e10":1,"e05":6,"e03":6,"e06":4}, +] +const EXPEDITION_TITLES: Array[String] = [ + "Erste Risse", "Splitterstrom", "Harte Schalen", "Fäden im Rücken", "Der Bruchhirsch", + "Gepanzerter Vorstoß", "Stimmen aus dem Nebel", "Gedeckter Vormarsch", "Die Knotenrufer", + "Der Riegelkoloss", "Splitterflut", "Heilende Front", "Nebel und Fäden", "Bruchlinie", + "Der Maskenrichter", "Der große Schwarm", "Stampfende Reihen", "Rissgesang", "Vor dem Schlund", "Die Schlundkrone" +] +const EXPEDITION_HINTS: Array[String] = [ + "", "", "", "", "", "", "", + "Eine breite Panzerfront schützt sechs Schützen. Kombiniere Durchschlag mit Flächenschaden.", + "NEU · Bruchstampfer treffen mehrere Ziele. Knotenrufer heilen verwundete Angreifer; konzentriere deinen Schaden.", + "BOSS · Riegelkoloss mit Startschild und ätherischer Begleitung. Durchschlag und Impuls ergänzen sich.", + "Ein großer Schwarm. Kraterrufer treffen mehrere Gegner; schütze deine Artillerie.", + "Schwere Front mit Heilern. Aufgewertete Glasballisten helfen gegen hohe Einzelziel-HP.", + "Nebelreste tragen ätherische Rüstung. Impulsschaden ist hier besonders wirksam.", + "Breite Nahkampfwelle: mehrere Frontkämpfer verteilen den Druck.", + "BOSS · Der Maskenrichter verlangsamt alle sechs Sekunden bis zu drei Wächter. Halte Schaden und Unterstützung bereit.", + "28 Angreifer: Flächenschaden und eine belastbare Front sind entscheidend.", + "Acht Bruchstampfer und vier Heiler. Werte deine Front und den Durchschlagschaden auf.", + "Ätherische Gegner und Fernkämpfer greifen gemeinsam an. Prüfe deine Schadensmischung.", + "Letzte Auszahlung vor dem Finale. Investiere Gold in die Formation und plane deine letzten Sends.", + "FINALE · Die Schlundkrone trifft bei jedem vierten Angriff mehrere Wächter. Nutze Gold und übrige Funken." +] + +func wave_count() -> int: + return EXPEDITION_WAVE_COUNT if GameState.match_mode == GameState.MODE_EXPEDITION else SHORT_WAVE_COUNT + +func get_unit(id: String) -> Dictionary: + return UNITS.get(id, {}).duplicate(true) + +func get_wave(wave: int) -> Dictionary: + if wave < 1 or wave > wave_count(): + return {} + var x: float = float(wave - 1) + var full: bool = GameState.match_mode == GameState.MODE_EXPEDITION + var groups: Dictionary = (EXPEDITION_WAVES if full else WAVES)[wave - 1].duplicate(true) + var count: int = 0 + var names: PackedStringArray = [] + for id: String in groups: + count += int(groups[id]) + names.append("%d × %s" % [groups[id], ENEMIES[id]["display_name"]]) + return {"number": wave, "groups": groups, "count": count, + "title": EXPEDITION_TITLES[wave - 1] if full else WAVE_TITLES[wave - 1], + "hint": EXPEDITION_HINTS[wave - 1] if full and wave > 7 else WAVE_HINTS[wave - 1], + "hp_factor": 1.0 + 0.10*x + 0.004*x*x if full else 1.0 + 0.14*x + 0.010*x*x, + "damage_factor": 1.0 + 0.06*x + 0.002*x*x if full else 1.0 + 0.08*x + 0.004*x*x, + "bounty_factor": 1.0 + 0.04 * x, "description": ", ".join(names)} + +func get_attackers(wave: int) -> Array: + var result: Array = [] + var info: Dictionary = get_wave(wave) + if info.is_empty(): + return result + for id: String in info["groups"]: + for _index: int in range(int(info["groups"][id])): + result.append(_scaled(ENEMIES[id], info, true)) + return result + +func get_send(id: String, wave: int) -> Dictionary: + var info: Dictionary = get_wave(wave) + if not SENDS.has(id) or info.is_empty(): + return {} + return _scaled(SENDS[id], info, false) + +func _scaled(source: Dictionary, wave: Dictionary, natural: bool) -> Dictionary: + var result: Dictionary = source.duplicate(true) + result["max_hp"] = ceil(float(source["max_hp"]) * float(wave["hp_factor"])) + result["damage"] = float(source["damage"]) * float(wave["damage_factor"]) + result["bounty"] = floori(float(source["bounty"]) * float(wave["bounty_factor"])) + result["hp_factor"] = wave["hp_factor"] + result["natural"] = natural + result["is_boss"] = source.get("is_boss", false) + result["cost"] = source.get("cost", 0) + result["upgrade_id"] = "" + result["color"] = Color("c4d2cd") if natural else Color("bc87bd") + return result + +const FACTIONS: Array[String] = ["glutpakt", "wurzelbund"] +const FACTION_NAMES: Dictionary = {"glutpakt": "Glutpakt", "wurzelbund": "Wurzelbund"} +const ROLES: Array[String] = ["Nahkampf", "Front / Tank", "Fernkampf", "Flächenschaden", "Unterstützung"] + +func base_ids(team: int = 0) -> Array[String]: + var prefix: String = "w" if GameState.factions[team] == "wurzelbund" else "g" + return [prefix+"01", prefix+"03", prefix+"05", prefix+"07", prefix+"09"] + +func faction_ids(faction: String) -> Array[String]: + var prefix: String = "w" if faction == "wurzelbund" else "g" + return [prefix+"01", prefix+"03", prefix+"05", prefix+"07", prefix+"09"] + +func for_team(id: String, team: int) -> String: + return ("w" + id.substr(1)) if id.begins_with("g") and GameState.factions[team] == "wurzelbund" else id + +func starter_cost(team: int = 0) -> int: + var ids := base_ids(team) + return int(UNITS[ids[0]].cost + UNITS[ids[1]].cost + UNITS[ids[2]].cost) + +func wave_hint(wave: int, team: int = 0) -> String: + var hint: String = str(get_wave(wave).get("hint", "")) + if GameState.factions[team] == "wurzelbund": + for number: int in range(1,11): + hint = hint.replace(UNITS["g%02d" % number].display_name, UNITS["w%02d" % number].display_name) + return hint diff --git a/scripts/data/data_catalog.gd.uid b/scripts/data/data_catalog.gd.uid new file mode 100644 index 0000000..22ecff3 --- /dev/null +++ b/scripts/data/data_catalog.gd.uid @@ -0,0 +1 @@ +uid://ccntaxqiayf8j diff --git a/scripts/main.gd b/scripts/main.gd new file mode 100644 index 0000000..5c31df2 --- /dev/null +++ b/scripts/main.gd @@ -0,0 +1,642 @@ +extends Node3D +## Thin input/presentation adapter. All economic actions enter the same command API. + +@onready var world: Node3D = $World +@onready var camera: Camera3D = $Camera3D +@onready var battle: Node3D = $BattleController +@onready var hud: Control = $CanvasLayer/HUD + +var selected_uid: int = -1 +var build_type: String = "" +var move_uid: int = -1 +var viewed_team: int = 0 +var _formation_dirty: bool = false +var _worker_roots: Array[Node3D] = [] +var _worker_counts: Array[int] = [-1, -1] +var _hover: MeshInstance3D +var _range: MeshInstance3D +var _focus: Vector3 = Vector3(-9.0, 0.0, 0.0) +var _camera_yaw: float = .20 +var _manual_camera: bool = false +var _dragging_camera: bool = false +var _readout_left: float = 0.0 +var _ghost: Node3D +var _base_view: bool = false +var _core_roots: Array[Node3D] = [] +var _core_texts: Array[Label3D] = [] +var _base_texts: Array[Label3D] = [] +var _visual_time: float = 0.0 +const StoneFloor = preload("res://scripts/presentation/stone_floor.gdshader") + + +func _ready() -> void: + DisplayServer.window_set_title("Saumwacht · Die grüne Kluft") + get_tree().auto_accept_quit = false + get_window().close_requested.connect(Soundscape.quit_game) + _make_world() + _place_camera() + WaveManager.attach_battle(battle) + EconomyManager.changed.connect(_on_economy_changed) + GameState.phase_changed.connect(_on_phase_changed) + hud.command_requested.connect(_on_command) + hud.build_selected.connect(_select_build) + hud.move_requested.connect(_begin_move) + hud.focus_requested.connect(_switch_front) + hud.base_requested.connect(_show_base) + hud.new_match_requested.connect(_start_match) + hud.menu_requested.connect(_return_menu) + hud.starter_requested.connect(_starter) + hud.cancel_requested.connect(_clear_selection) + hud.ready_requested.connect(WaveManager.ready_for_battle) + # World and controls are already visible behind the opening panel. + battle.show_formation([[], []]) + if "--ringborke" in OS.get_cmdline_user_args(): + hud.model_inspector.call_deferred("show_model","w04") + if "--smoke-test" in OS.get_cmdline_user_args(): + var smoke: Node = load("res://scripts/qa/export_smoke.gd").new() + add_child(smoke) + smoke.call_deferred("run", self) + elif "--faction-test" in OS.get_cmdline_user_args(): + var test: Node = load("res://scripts/qa/faction_test.gd").new() + add_child(test) + test.call_deferred("run", self) + elif "--expedition-test" in OS.get_cmdline_user_args(): + var acceptance: Node = load("res://scripts/qa/expedition_test.gd").new() + add_child(acceptance) + acceptance.call_deferred("run",self) + + +func _start_match() -> void: + _clear_selection() + viewed_team = 0 + Soundscape.viewed_team = 0 + _reset_camera() + _place_camera() + WaveManager.start_match() + hud.notify("Setze die Startformation für %d Gold oder wähle einzelne Wächter. Du bestimmst, wann der Kampf beginnt." % DataCatalog.starter_cost()) + + +func _on_phase_changed(_phase: int) -> void: + _clear_ghost() + _base_view = false + build_type = "" + move_uid = -1 + hud.build_type = "" + _hover.visible = false + _range.visible = false + if _phase == GameState.Phase.BUILD: + _focus.z = 0.0 + _manual_camera = false + camera.size = 27.0 + _place_camera() + elif _phase == GameState.Phase.COMBAT: + camera.size = 23.0 + if _phase == GameState.Phase.MENU: + hud.viewed_team = 0 + + +func _on_economy_changed(_team: int) -> void: + _formation_dirty = true + + +func _process(delta: float) -> void: + _visual_time += delta + _animate_base(delta) + _follow_combat(delta) + for unit: CombatUnit in battle.units: + if unit.alive: + unit.face_health_bars(camera.global_basis) + _readout_left -= delta + if _readout_left <= 0.0: + _readout_left = .10 + hud.update_battle_readout(battle.units, _manual_camera or not Preferences.follow_camera) + if _formation_dirty and GameState.phase == GameState.Phase.BUILD: + _formation_dirty = false + battle.show_formation([ + EconomyManager.get_team(0).roster, EconomyManager.get_team(1).roster + ]) + _update_selection_visuals() + _refresh_workers() + _update_hover() + + +func _input(event: InputEvent) -> void: + if hud.model_inspector.visible: + if event is InputEventKey and event.pressed and event.keycode in [KEY_ESCAPE,KEY_V]: + hud.model_inspector.hide_model() + get_viewport().set_input_as_handled() + elif event is InputEventKey and event.keycode == KEY_SPACE: + get_viewport().set_input_as_handled() + return + if event is InputEventKey and event.pressed and not event.echo and event.keycode == KEY_V and not hud.settings_panel.visible: + hud.inspect_selected_model() + get_viewport().set_input_as_handled() + return + if event is InputEventKey and event.pressed and not event.echo: + if event.keycode == KEY_F1 or (event.keycode == KEY_ESCAPE and hud.settings_panel.visible): + hud.toggle_settings() + get_viewport().set_input_as_handled() + return + if event.keycode in [KEY_M, KEY_F11]: + if event.keycode == KEY_M: + Preferences.muted = not Preferences.muted + else: + Preferences.fullscreen = not Preferences.fullscreen + Preferences.commit() + hud.sync_settings() + get_viewport().set_input_as_handled() + return + if hud.settings_panel.visible: + return + # The title menu, including its fade after "Partie beginnen", keeps game keys out of play. + if GameState.phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER] or hud.main_menu.visible: + return + if event is InputEventKey and event.pressed and not event.echo: + var handled := true + match event.keycode: + KEY_1, KEY_2, KEY_3, KEY_4, KEY_5: + _select_build(DataCatalog.base_ids()[event.keycode - KEY_1]) + KEY_SPACE: + hud.request_wave_start() + KEY_P: + hud.toggle_pause() + KEY_C: + _show_base() + KEY_TAB: + _switch_front() + KEY_ESCAPE: + _clear_selection() + KEY_Q, KEY_E: + _camera_yaw += .35 * (-1 if event.keycode == KEY_Q else 1) + _place_camera() + KEY_R: + _reset_camera() + _: + handled = false + # Space/Tab must keep their game meaning even after a button has focus. + if handled: + get_viewport().set_input_as_handled() + + +func _unhandled_input(event: InputEvent) -> void: + if hud.settings_panel.visible or hud.model_inspector.visible or hud.main_menu.visible or GameState.phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER]: + return + if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_MIDDLE: + _dragging_camera = event.pressed + if event is InputEventMouseMotion and _dragging_camera: + if not event.button_mask & MOUSE_BUTTON_MASK_MIDDLE: + _dragging_camera = false + return + _manual_camera = true + var right: Vector3 = camera.global_basis.x + var forward: Vector3 = camera.global_basis.z + right.y = 0 + forward.y = 0 + _focus += (-right.normalized() * event.relative.x - forward.normalized() * event.relative.y) * camera.size / 600.0 + _focus.x = clampf(_focus.x, -20, 20) + _focus.z = clampf(_focus.z, -14, 18) + _place_camera() + if event is InputEventMouseButton and event.pressed: + if event.button_index == MOUSE_BUTTON_RIGHT: + _clear_selection() + elif event.button_index == MOUSE_BUTTON_WHEEL_UP: + camera.size = maxf(14.0, camera.size - 1.5) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + camera.size = minf(42.0, camera.size + 1.5) + elif event.button_index == MOUSE_BUTTON_LEFT: + _click_field(event.position) + + +func _mouse_cell(mouse: Vector2 = Vector2(-1, -1)) -> Vector2i: + if mouse == Vector2(-1, -1): + mouse = get_viewport().get_mouse_position() + var origin: Vector3 = camera.project_ray_origin(mouse) + var direction: Vector3 = camera.project_ray_normal(mouse) + var hit = Plane(Vector3.UP, 0.0).intersects_ray(origin, direction) + if hit == null: + return Vector2i(-1, -1) + var center: float = -9.0 if viewed_team == 0 else 9.0 + var cell := Vector2i(int(floor((hit.x - center + 6.0) / 2.0)), + int(floor((hit.z + 8.0) / 2.0))) + if cell.x < 0 or cell.x >= 6 or cell.y < 0 or cell.y >= 8: + return Vector2i(-1, -1) + return cell + + +func _click_field(mouse: Vector2) -> void: + if GameState.phase != GameState.Phase.BUILD or viewed_team != 0: + return + if build_type.is_empty() and move_uid < 0: + # Hit the visible figure as well as its floor cell; tall models hide their feet. + var closest: float = 38.0 + var picked: int = -1 + for unit: CombatUnit in battle.units: + if unit.team_id != 0 or unit.is_attacker: + continue + var screen: Vector2 = camera.unproject_position(unit.position + Vector3.UP * unit.visual_height * .45) + var distance: float = screen.distance_to(mouse) + if distance < closest: + closest = distance + picked = unit.uid + if picked >= 0: + selected_uid = picked + hud.selected_uid = picked + _update_selection_visuals() + return + var cell := _mouse_cell(mouse) + if cell.x < 0: + return + if move_uid >= 0: + _on_command({"type": "move", "uid": move_uid, "cell": cell}) + move_uid = -1 + elif not build_type.is_empty(): + var placed: bool = _on_command({"type": "build", "type_id": build_type, "cell": cell}) + if placed and not Input.is_key_pressed(KEY_SHIFT): + _clear_selection() + for entry: Dictionary in EconomyManager.get_team(0).roster: + if entry.cell == cell: + selected_uid = entry.uid + hud.selected_uid = entry.uid + else: + selected_uid = -1 + for entry in EconomyManager.get_team(0).roster: + if entry.cell == cell: + selected_uid = int(entry.uid) + break + hud.selected_uid = selected_uid + _update_selection_visuals() + + +func _select_build(type_id: String) -> void: + if GameState.phase != GameState.Phase.BUILD: + return + if viewed_team != 0: + _switch_front() + if _base_view: + _reset_camera() + _clear_ghost() + _ghost = AssetLibrary.instantiate_model(type_id) + if _ghost != null: + world.add_child(_ghost) + _ghost.rotation.y = PI + var ghost_material := _material(Color(.48, .95, .72, .38), true) + _ghost.material_override = ghost_material + _ghost.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF + build_type = type_id + move_uid = -1 + selected_uid = -1 + hud.selected_uid = -1 + hud.build_type = type_id + hud.notify("%s platzieren · Rechtsklick bricht ab" % DataCatalog.get_unit(type_id).display_name) + _update_selection_visuals() + + +func _begin_move() -> void: + if selected_uid < 0 or GameState.phase != GameState.Phase.BUILD: + return + move_uid = selected_uid + build_type = "" + hud.build_type = "" + hud.notify("Neuen freien Platz wählen. Versetzen ist kostenlos.") + + +func _on_command(command: Dictionary) -> bool: + var result: Dictionary = EconomyManager.apply_command(0, command) + if result.ok: + Soundscape.play("place") + hud.notify(str(result.get("message", "Auftrag ausgeführt."))) + else: + Soundscape.play("error") + hud.notify(str(result.message), true) + return bool(result.ok) + + +func _starter() -> void: + if GameState.phase != GameState.Phase.BUILD: + return + if not EconomyManager.get_team(0).roster.is_empty(): + hud.notify("Die Startformation benötigt ein leeres Baufeld.", true) + return + if EconomyManager.get_team(0).gold < DataCatalog.starter_cost(): + hud.notify("Für die komplette Startformation fehlen %d Gold." % + (DataCatalog.starter_cost() - int(EconomyManager.get_team(0).gold)), true) + return + _on_command({"type": "build", "type_id": DataCatalog.for_team("g03", 0), "cell": Vector2i(2, 2)}) + _on_command({"type": "build", "type_id": DataCatalog.for_team("g01", 0), "cell": Vector2i(3, 2)}) + _on_command({"type": "build", "type_id": DataCatalog.for_team("g05", 0), "cell": Vector2i(2, 4)}) + hud.notify("Startformation aufgestellt · %d Gold bezahlt. Leertaste startet den Kampf." % DataCatalog.starter_cost()) + + +func _clear_selection() -> void: + _clear_ghost() + selected_uid = -1 + build_type = "" + move_uid = -1 + hud.selected_uid = -1 + hud.build_type = "" + _update_selection_visuals() + + +func _switch_front() -> void: + viewed_team = 1 - viewed_team + _focus.x = -9.0 if viewed_team == 0 else 9.0 + _manual_camera = false + Soundscape.viewed_team = viewed_team + _place_camera() + hud.viewed_team = viewed_team + _clear_selection() + + +func _place_camera() -> void: + var offset: Vector3 = Vector3(0, 29, 28).rotated(Vector3.UP, _camera_yaw) + camera.position = _focus + offset + camera.look_at(_focus, Vector3.UP) + # Move the arena into the area left of the inspector and above the shop. + var shift: Vector3 = camera.global_basis.x * camera.size * .17 - camera.global_basis.y * camera.size * .015 + camera.position += shift + +func _reset_camera() -> void: + _base_view = false + _focus = Vector3(-9.0 if viewed_team == 0 else 9.0, 0, 0) + _camera_yaw = .20 + _manual_camera = false + camera.size = 23.0 if GameState.phase == GameState.Phase.COMBAT else 29.0 + _place_camera() + + +func _update_hover() -> void: + var cell := _mouse_cell() + var over_ui: bool = get_viewport().gui_get_hovered_control() != null + _hover.visible = GameState.phase == GameState.Phase.BUILD and viewed_team == 0 and cell.x >= 0 and not over_ui + if is_instance_valid(_ghost): + _ghost.visible = _hover.visible + if not _hover.visible: + _range.visible = false + return + _hover.position = Vector3(-14.0 + cell.x * 2, 0.035, -7.0 + cell.y * 2) + var occupied := false + for entry in EconomyManager.get_team(0).roster: + if entry.cell == cell: + occupied = true + if is_instance_valid(_ghost): + _ghost.position = _hover.position + _ghost.visible = not occupied + var mat: StandardMaterial3D = _hover.material_override + mat.albedo_color = Color(0.9, 0.36, 0.27, 0.6) if occupied else Color(0.5, 0.85, 0.74, 0.45) + if not build_type.is_empty(): + var unit_data: Dictionary = DataCatalog.get_unit(build_type) + var mesh: CylinderMesh = _range.mesh + mesh.top_radius = unit_data.attack_range + mesh.bottom_radius = unit_data.attack_range + _range.position = _hover.position + Vector3(0, 0.02, 0) + _range.visible = true + else: + _range.visible = false + + +func _update_selection_visuals() -> void: + if not is_instance_valid(battle): + return + for unit in battle.units: + if is_instance_valid(unit) and unit.has_method("set_selected"): + unit.set_selected(unit.uid == selected_uid and not unit.is_attacker and unit.team_id == 0) + + +func _material(color: Color, unshaded: bool = false) -> StandardMaterial3D: + var mat := StandardMaterial3D.new() + mat.albedo_color = color + mat.roughness = 0.88 + if unshaded: + mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + if color.a < 1.0: + mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + return mat + + +func _box(size: Vector3, pos: Vector3, color: Color) -> MeshInstance3D: + var instance := MeshInstance3D.new() + var mesh := BoxMesh.new() + mesh.size = size + instance.mesh = mesh + instance.material_override = _material(color) + instance.position = pos + world.add_child(instance) + return instance + + +func _make_world() -> void: + var sanctuary := preload("res://scripts/presentation/sanctuary.gd").new() + world.add_child(sanctuary) + var grid_materials: Array[ShaderMaterial] = [] + for color: Color in [Color("5a6358"), Color("4e5850")]: + var material := ShaderMaterial.new() + material.shader = StoneFloor + material.set_shader_parameter("stone_color", color) + material.set_shader_parameter("limestone", preload("res://assets/materials/phase10/limestone-albedo.png")) + material.set_shader_parameter("build_tile", true) + grid_materials.append(material) + var environment := WorldEnvironment.new() + var settings := Environment.new() + preload("res://scripts/presentation/lighting.gd").configure(settings) + environment.environment = settings + world.add_child(environment) + var sun := DirectionalLight3D.new() + sun.rotation_degrees = Vector3(-52, -38, 0) + sun.light_color = Color("#ffd4a0") + sun.light_energy = 1.85 + sun.light_angular_distance = 1.2 + sun.shadow_enabled = true + sun.directional_shadow_max_distance = 100.0 + sun.directional_shadow_fade_start = .7 + sun.shadow_blur = 2.2 + sun.directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS + sun.directional_shadow_split_1 = .08 + sun.directional_shadow_split_2 = .22 + sun.directional_shadow_split_3 = .45 + sun.directional_shadow_pancake_size = 2.5 + world.add_child(sun) + var fill := DirectionalLight3D.new() + fill.rotation_degrees = Vector3(-32, 148, 0) + fill.light_color = Color("a8c4e8") + fill.light_energy = .48 + fill.light_angular_distance = 2.0 + world.add_child(fill) + var rim := DirectionalLight3D.new() + rim.rotation_degrees = Vector3(-18, 55, 0) + rim.light_color = Color("c8e8d8") + rim.light_energy = .22 + world.add_child(rim) + for team in range(2): + var center: float = -9.0 if team == 0 else 9.0 + var accent := Color("#64c6b1") if team == 0 else Color("#e29074") + for row in range(8): + for column in range(6): + var color := Color("55545a") if (row + column) % 2 == 0 else Color("4b4b52") + var grid_tile := _box(Vector3(1.94, 0.025, 1.94), Vector3(center - 5 + column * 2, .014, -7 + row * 2), color) + grid_tile.material_override = grid_materials[(row + column) % 2] + _box(Vector3(12, .03, .10), Vector3(center, .045, -8.1), accent) + _box(Vector3(12, .03, .15), Vector3(center, .045, 16), accent) + var core: Node3D = AssetLibrary.instantiate_fighter("core_team%d" % team) + if core != null: + core.position = Vector3(center, 0, 18.2) + world.add_child(core) + _core_roots.append(core) + if core.has_method("trigger_activate"): + core.trigger_activate() + else: + _box(Vector3(2, 2.2, 2), Vector3(center, 1.1, 18.2), accent) + var workers := Node3D.new() + workers.name = "Workers_Team%d" % team + world.add_child(workers) + _worker_roots.append(workers) + var label := Label3D.new() + label.text = "DEIN SAUMKERN" if team == 0 else "RIVALENKERN" + label.font_size = 36 + label.outline_size = 3 + label.pixel_size = 0.006 + label.position = Vector3(center, 3.3, 18.2) + label.billboard = BaseMaterial3D.BILLBOARD_ENABLED + label.modulate = accent + world.add_child(label) + _core_texts.append(label) + var core_light := OmniLight3D.new() + core_light.position = Vector3(center, 1.6, 18.2) + core_light.light_color = accent + core_light.light_energy = 2.4 + core_light.light_volumetric_fog_energy = 1.8 + core_light.omni_range = 7.5 + core_light.omni_attenuation = 1.4 + world.add_child(core_light) + var production := Label3D.new() + production.font_size = 30 + production.outline_size = 3 + production.pixel_size = .006 + production.billboard = BaseMaterial3D.BILLBOARD_ENABLED + production.position = Vector3(center, 2.3, 12.5) + production.modulate = accent + world.add_child(production) + _base_texts.append(production) + # Route markers make front/back readable independently of camera rotation. + for z: float in [-10.0, 9.2]: + var direction := Label3D.new() + direction.text = "▼ HIER KOMMEN DIE GEGNER ▼" if z < 0 else "RÜCKRAUM · SCHÜTZEN & HEILER" + direction.position = Vector3(center, .08, z) + direction.rotation_degrees.x = -90 + direction.font_size = 32 + direction.outline_size = 3 + direction.pixel_size = .006 + direction.modulate = accent + world.add_child(direction) + _hover = _box(Vector3(1.9, 0.02, 1.9), Vector3.ZERO, Color(0.4, 0.9, 0.7, 0.4)) + _hover.visible = false + _range = MeshInstance3D.new() + var range_mesh := CylinderMesh.new() + range_mesh.height = 0.012 + range_mesh.radial_segments = 64 + _range.mesh = range_mesh + _range.material_override = _material(Color(0.5, 0.9, 0.75, 0.10), true) + world.add_child(_range) + _range.visible = false + + +func _refresh_workers() -> void: + for team: int in range(_worker_roots.size()): + var count: int = int(EconomyManager.get_team(team).get("workers", 0)) + if count == _worker_counts[team]: + continue + _worker_counts[team] = count + for child: Node in _worker_roots[team].get_children(): + child.free() + for index: int in range(count): + var worker: Node3D = AssetLibrary.instantiate_fighter("worker") + if worker == null: + continue + _worker_roots[team].add_child(worker) + var center: float = -9.0 if team == 0 else 9.0 + worker.position = Vector3(center - 4.2 + (index % 4) * 2.8, 0, 13.7 + floori(index / 4.0) * 2.2) + worker.set_meta("home", worker.position) + worker.rotation.y = 0.0 + # Shared cut-mineral geometry marks each worker's gathering station. + if AssetLibrary._rigs.has("core_team%d" % team): + var ore := MeshInstance3D.new() + ore.mesh = AssetLibrary._rigs["core_team%d" % team].groups.Crystal.mesh + ore.scale = Vector3.ONE * .22 + ore.position = Vector3(.0,.25,.65) + worker.add_child(ore) + + +func _follow_combat(delta: float) -> void: + if GameState.phase != GameState.Phase.COMBAT or GameState.paused or _manual_camera or _base_view or not Preferences.follow_camera: + return + var sum_z: float = 0.0 + var count: int = 0 + for unit: CombatUnit in battle.units: + if unit.alive and unit.team_id == viewed_team: + sum_z += unit.position.z + count += 1 + if count > 0: + _focus.z = lerpf(_focus.z, clampf(sum_z / count, -7.0, 12.0), minf(1.0, delta * 2.5)) + _place_camera() + +func _clear_ghost() -> void: + if is_instance_valid(_ghost): + _ghost.free() + _ghost = null + +func _show_base() -> void: + if GameState.phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER]: + return + if _base_view: + _reset_camera() + return + _clear_selection() + _base_view = true + _manual_camera = true + _focus = Vector3(-9.0 if viewed_team == 0 else 9.0, 0.0, 15.2) + _camera_yaw = .20 + camera.size = 14.0 + _place_camera() + hud.notify("Arbeiter sammeln je 10 Funken pro Welle. Schütze den Kristall · C zurück zur Front.") + +func _animate_base(delta: float) -> void: + for team: int in range(_core_roots.size()): + var hp: int = int(GameState.core_hp[team]) + if _core_roots[team].has_method("set_core_health"): + _core_roots[team].set_core_health(hp / 3000.0) + if _core_roots[team].has_method("pose"): + _core_roots[team].pose(_visual_time, false, 0, 0, 0, delta) + _core_texts[team].text = ("DEIN KRISTALL" if team == 0 else "RIVALENKRISTALL") + " · %d / 3000" % hp + _core_texts[team].modulate = Color("e9967c") if hp < 1000 else (Color("83cfbd") if team == 0 else Color("e9967c")) + var state: Dictionary = EconomyManager.get_team(team) + _base_texts[team].text = "%d ARBEITER · +%d FUNKEN / WELLE%s" % [state.workers, int(state.workers)*10, "\n%d IN AUSBILDUNG" % state.pending_workers if state.pending_workers else ""] + var time: float = _visual_time if not GameState.paused else 0.0 + var step: float = 0.0 if GameState.paused else delta + for index: int in range(_worker_roots[team].get_child_count()): + var worker: Node3D = _worker_roots[team].get_child(index) + if worker.has_method("update_work"): + worker.update_work(step, index * .83) + if worker.has_method("consume_strike_contact") and worker.consume_strike_contact(): + _flash_worker_ore(worker) + elif worker.has_method("pose"): + worker.pose(time + index * .7, false, fmod(time + index * .4, 2.4) * .12, 0, 0) + for child: Node in worker.get_children(): + if child is MeshInstance3D: + child.scale = child.scale.lerp(Vector3.ONE * .22, minf(1.0, step * 6.0)) + worker.position = worker.get_meta("home") + Vector3(0, sin(time*2+index)*.025, 0) + +func _flash_worker_ore(worker: Node3D) -> void: + for child: Node in worker.get_children(): + if child is MeshInstance3D: + child.scale = Vector3.ONE * .32 + +func _return_menu() -> void: + Soundscape.stop_combat() + _clear_selection() + viewed_team = 0 + hud.viewed_team = 0 + Soundscape.viewed_team = 0 + GameState.reset_match() + EconomyManager.reset_match() + WaveManager.remaining = 0.0 + battle.show_formation([[], []]) + _reset_camera() diff --git a/scripts/main.gd.uid b/scripts/main.gd.uid new file mode 100644 index 0000000..bafa711 --- /dev/null +++ b/scripts/main.gd.uid @@ -0,0 +1 @@ +uid://cjyvh4t0pkvr5 diff --git a/scripts/presentation/animated_figure.gd b/scripts/presentation/animated_figure.gd new file mode 100644 index 0000000..af12262 --- /dev/null +++ b/scripts/presentation/animated_figure.gd @@ -0,0 +1,89 @@ +extends Node3D +## Rigid stone joints: meshes shared across units, transforms owned per instance. + +var asset_id: String = "" +var parts: Dictionary = {} +var rest_bounds: AABB +var _walk: float = 0.0 +var _hit_material: StandardMaterial3D +var _core_health: float = 1.0 +var _core_damage: float = 0.0 +var _core_activate: float = 0.0 + +func setup(id: String, groups: Dictionary, bounds: AABB) -> void: + asset_id = id + rest_bounds = bounds + name = "Animated_" + id + _hit_material = StandardMaterial3D.new() + _hit_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + _hit_material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + _hit_material.albedo_color = Color(1.0, .83, .49, 0.0) + for key: String in groups: + var instance := MeshInstance3D.new() + instance.name = key + instance.mesh = groups[key].mesh + instance.position = groups[key].pivot + instance.set_meta("rest", instance.position) + instance.material_overlay = _hit_material + add_child(instance) + parts[key] = instance + +func set_core_health(ratio: float) -> void: + var next: float = clampf(ratio, 0.0, 1.0) + if next < _core_health - .002: + _core_damage = 1.0 + _core_health = next + +func trigger_activate() -> void: + _core_activate = 1.0 + +func pose(time: float, moving: bool, attack: float, ability: float, hit: float, delta: float = 0.0) -> void: + _walk = move_toward(_walk, 1.0 if moving else 0.0, .12) + var stride: float = sin(time * 8.0) * _walk + var strike: float = sin(clampf(attack / .28, 0.0, 1.0) * PI) + _core_damage = maxf(0.0, _core_damage - delta * 1.8) + _core_activate = maxf(0.0, _core_activate - delta * .55) + _hit_material.albedo_color.a = clampf(maxf(hit * 2.4, _core_damage * .45), 0.0, .5) + for key: String in parts: + var part: MeshInstance3D = parts[key] + part.position = part.get_meta("rest") + part.rotation = Vector3.ZERO + part.scale = Vector3.ONE + if key.begins_with("Leg"): + var side: float = 1.0 if key.begins_with("LegL") else -1.0 + if key.right(1).is_valid_int() and int(key.right(1)) % 2 == 1: + side *= -1.0 + part.rotation.x = stride * side * .30 + part.position.y += maxf(0, stride * side) * .05 + continue + match key: + "ArmL", "ArmR": + var side: float = 1.0 if key == "ArmL" else -1.0 + part.rotation.x = -stride * side * .16 - strike * (.52 if asset_id in ["g01","g02","g03","g04","e05","e08"] else .12) + part.rotation.z = strike * side * .08 + "Weapon": + part.position.z -= strike * (.22 if asset_id == "g06" else .10) + if asset_id == "g05": + part.rotation.y = strike * .22 + "Mortar": + part.rotation.x = -strike * .16 + part.position.y -= strike * .07 + "Flame": + part.scale.y = 1.0 + sin(time * 11.0) * .09 + ability * .45 + "Crystal": + # Activation flare, calm float, then a readable shudder when hurt. + var distress: float = 1.0 - _core_health + var pulse: float = sin(time * (1.5 + distress * 2.2)) + part.position.y += pulse * (.045 + distress * .018) + _core_activate * .14 + part.rotation.y = sin(time * .35) * .08 + _core_damage * .16 * sin(time * 36.0) + part.scale = Vector3.ONE * (1.0 + _core_activate * .18 + _core_damage * .07) + "Body": + part.rotation.z = stride * .025 + if asset_id in ["e03","e06","e09"]: + part.position.y += sin(time*2.4)*.06 + if asset_id == "e10": + part.rotation.x = -strike*.15 + part.position.z -= strike*.10 + +func get_aabb() -> AABB: + return rest_bounds diff --git a/scripts/presentation/animated_figure.gd.uid b/scripts/presentation/animated_figure.gd.uid new file mode 100644 index 0000000..94d33de --- /dev/null +++ b/scripts/presentation/animated_figure.gd.uid @@ -0,0 +1 @@ +uid://datm3p3nv42tq diff --git a/scripts/presentation/arbeiter.gdshader b/scripts/presentation/arbeiter.gdshader new file mode 100644 index 0000000..0e2fc61 --- /dev/null +++ b/scripts/presentation/arbeiter.gdshader @@ -0,0 +1,58 @@ +shader_type spatial; +// The imported AB/BB/QG surfaces are double-sided, including thin foliage. +render_mode diffuse_burley, specular_schlick_ggx, cull_disabled; +uniform float roughness_value : hint_range(0, 1) = 0.75; +uniform float metallic_value : hint_range(0, 1) = 0.0; +uniform float grain_amount = 0.08; +uniform float grain_scale = 90.0; +uniform float relief_depth = 0.00045; +// 0 mineral, 1 leather, 2 fabric, 3 bark, 4 leaf, 5 metal. +uniform int surface_kind = 0; + +float hash21(vec2 p) { + p = fract(p * vec2(123.34, 456.21)); + p += dot(p, p + 45.32); + return fract(p.x * p.y); +} + +float grain_noise(vec2 p) { + vec2 cell = floor(p); + vec2 f = fract(p); + vec2 blend = f * f * (3.0 - 2.0 * f); + return mix(mix(hash21(cell), hash21(cell + vec2(1.0, 0.0)), blend.x), + mix(hash21(cell + vec2(0.0, 1.0)), hash21(cell + vec2(1.0)), blend.x), blend.y); +} + +void fragment() { + if (!FRONT_FACING) { NORMAL = -NORMAL; } + vec2 p = UV * grain_scale; + float footprint = max(length(dFdx(p)), length(dFdy(p))); + float detail = 1.0 - smoothstep(0.5, 2.0, footprint); + float coarse = grain_noise(p * 0.37); + float fine = grain_noise(p) * 0.65 + grain_noise(p * 2.03 + 19.7) * 0.35; + float grain = mix(0.0, fine - 0.5, detail); + float relief = grain; + if (surface_kind == 2) { + // Subpixel weave fades out instead of producing a moving checkerboard. + float weave = sin(p.x * 6.28318) * sin(p.y * 6.28318); + relief += weave * detail * 0.1; + } else if (surface_kind == 3) { + relief = (grain_noise(vec2(p.x, p.y * 0.12)) - 0.5) * detail; + } else if (surface_kind == 4) { + relief *= 0.2; + BACKLIGHT = COLOR.rgb * 0.12; + } else if (surface_kind == 5) { + relief = (grain_noise(vec2(p.x * 0.1, p.y)) - 0.5) * detail * 0.2; + } + ALBEDO = COLOR.rgb * (1.0 + grain * grain_amount + (coarse - 0.5) * grain_amount * 0.35); + ROUGHNESS = clamp(roughness_value + grain * 0.07, 0.08, 1.0); + METALLIC = metallic_value; + // Surface gradient in view space; preserves authored UVs while joints deform. + vec3 dx = dFdx(VERTEX), dy = dFdy(VERTEX); + vec3 rx = cross(dy, NORMAL), ry = cross(NORMAL, dx); + float determinant = dot(dx, rx); + if (abs(determinant) > 0.00000001) { + NORMAL = normalize(abs(determinant) * NORMAL - sign(determinant) * + (dFdx(relief) * rx + dFdy(relief) * ry) * relief_depth); + } +} diff --git a/scripts/presentation/arbeiter.gdshader.uid b/scripts/presentation/arbeiter.gdshader.uid new file mode 100644 index 0000000..d6d2098 --- /dev/null +++ b/scripts/presentation/arbeiter.gdshader.uid @@ -0,0 +1 @@ +uid://g5xaty0i2my3 diff --git a/scripts/presentation/asset_library.gd b/scripts/presentation/asset_library.gd new file mode 100644 index 0000000..84b92ec --- /dev/null +++ b/scripts/presentation/asset_library.gd @@ -0,0 +1,271 @@ +extends Node +## Resolve IDs once; keep source GLBs editable while batching static parts at runtime. + +var _models: Dictionary = {} +var _icons: Dictionary = {} +var _meshes: Dictionary = {} +var _textures: Dictionary = {} +var _rigs: Dictionary = {} +var _surface_materials: Dictionary = {} +const LivingMaterial = preload("res://scripts/presentation/living_material.gdshader") +const ForgedMaterial = preload("res://scripts/presentation/forged_material.gdshader") +const PrismaticCore = preload("res://scripts/presentation/prismatic_core.gdshader") +const AnimatedFigure = preload("res://scripts/presentation/animated_figure.gd") +const SkeletalFigure = preload("res://scripts/presentation/skeletal_figure.gd") +const WorkerFigure = preload("res://scripts/presentation/worker_figure.gd") +const RingborkeMaterial = preload("res://scripts/presentation/ringborke.gdshader") +const ArbeiterMaterial = preload("res://scripts/presentation/arbeiter.gdshader") +var missing: Array[String] = [] + +func _ready() -> void: + for entry: Dictionary in _read_manifest("res://assets/phase4_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase11_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase12_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase15_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase16_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase18_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase19_manifest.json"): + _models[str(entry.id)] = entry + for entry: Dictionary in _read_manifest("res://assets/phase3_manifest.json"): + _icons[str(entry.id)] = str(entry.resource_path) + _icons["worker"] = _icons.get("worker_funkenleser", "") + +func _read_manifest(path: String) -> Array: + if not FileAccess.file_exists(path): + return [] + var value: Variant = JSON.parse_string(FileAccess.get_file_as_string(path)) + return value.get("assets", []) if value is Dictionary else [] + +func icon(id: String) -> Texture2D: + if not _textures.has(id): + var path: String = _icons.get(id, "") + _textures[id] = load(path) as Texture2D if not path.is_empty() and ResourceLoader.exists(path) else null + return _textures[id] + +func model_height(id: String) -> float: + var record: Dictionary = _models.get(id, {}) + var bounds: Dictionary = record.get("bounds_godot", {}) + return float(bounds.get("max", [0, 1.6, 0])[1]) + +func instantiate_model(id: String) -> Node3D: + if not _models.has(id): + return null + if not _meshes.has(id): + var path: String = str(_models[id].resource_path) + if not ResourceLoader.exists(path): + if not missing.has(id): + missing.append(id) + push_warning("Missing visual asset: " + id) + return null + var packed: PackedScene = load(path) as PackedScene + if packed == null: + return null + var source: Node3D = packed.instantiate() as Node3D + var mesh: ArrayMesh = bake_mesh(source) + source.free() + _meshes[id] = mesh + var instance := MeshInstance3D.new() + instance.name = "Model_" + id + instance.mesh = _meshes[id] + instance.set_meta("asset_id", id) + return instance + +func bake_mesh(source: Node3D) -> ArrayMesh: + var surfaces: Dictionary = {} + _collect(source, Transform3D.IDENTITY, surfaces) + var mesh := ArrayMesh.new() + for material: Material in surfaces: + var builder: SurfaceTool = surfaces[material] + builder.set_material(material) + builder.commit(mesh) + return mesh + +func instantiate_fighter(id: String) -> Node3D: + if _models.get(id, {}).get("skeletal", false): + var scene := load(str(_models[id].resource_path)) as PackedScene + var source: Node3D = scene.instantiate() + decorate_model(source) + var info: Dictionary = _models[id].bounds_godot + var low := Vector3(info.min[0],info.min[1],info.min[2]) + var high := Vector3(info.max[0],info.max[1],info.max[2]) + var box := AABB(low,high-low) + if id == "worker": + var worker := WorkerFigure.new() + worker.setup(source, box) + return worker + var figure := SkeletalFigure.new() + figure.setup(source,box) + if _models[id].has("attack_cycle"): + figure.attack_cycle.assign(_models[id].attack_cycle) + return figure + if not (id.begins_with("g") or id.begins_with("e") or id.begins_with("w") or id.begins_with("core_team")) or not _models.has(id): + return instantiate_model(id) + if not _rigs.has(id): + var packed := load(str(_models[id].resource_path)) as PackedScene + if packed == null: + return instantiate_model(id) + var source := packed.instantiate() as Node3D + var groups: Dictionary = {} + _collect_rig(source, Transform3D.IDENTITY, id, groups) + var meshes: Dictionary = {} + var bounds := AABB() + var first: bool = true + for key: String in groups: + var mesh := ArrayMesh.new() + for material: Material in groups[key]: + var builder: SurfaceTool = groups[key][material] + builder.set_material(material) + builder.commit(mesh) + var box: AABB = mesh.get_aabb() + bounds = box if first else bounds.merge(box) + first = false + # Meshes are collected in model space. Move their vertices around joints. + var pivot: Vector3 = box.get_center() + if key.begins_with("Leg") or key.begins_with("Arm"): + pivot.y = box.end.y - box.size.y * .10 + elif key == "Flame": + pivot.y = box.position.y + var centered := ArrayMesh.new() + for surface: int in range(mesh.get_surface_count()): + var builder := SurfaceTool.new() + builder.begin(Mesh.PRIMITIVE_TRIANGLES) + builder.append_from(mesh, surface, Transform3D(Basis.IDENTITY, -pivot)) + builder.set_material(mesh.surface_get_material(surface)) + builder.commit(centered) + meshes[key] = {"mesh": centered, "pivot": pivot} + source.free() + _rigs[id] = {"groups": meshes, "bounds": bounds} + var figure := AnimatedFigure.new() + figure.setup(id, _rigs[id].groups, _rigs[id].bounds) + return figure + +func _collect_rig(node: Node3D, parent: Transform3D, id: String, groups: Dictionary) -> void: + var transform: Transform3D = parent * node.transform + if node is MeshInstance3D and node.mesh != null: + var part_name: String = str(node.name) + var key: String = "Body" + for prefix: String in ["LegL", "LegR", "ArmL", "ArmR", "Weapon"]: + if part_name.begins_with(prefix): + key = prefix + if part_name.begins_with("Leg"): + key = part_name.get_slice("_", 0) + if part_name.begins_with("WeaponL_"): + key = "ArmL" + elif part_name.begins_with("WeaponR_"): + key = "ArmR" + if part_name.begins_with("Core_Crystal"): + key = "Crystal" + if id.begins_with("w") and part_name.begins_with("Head_"): + key = "Weapon" + if id == "g05" and key.begins_with("Arm"): + key = "Weapon" + if id in ["g07", "g08"] and (part_name.begins_with("Body_Mortar") or part_name.begins_with("Body_Rim") or key == "Weapon"): + key = "Mortar" + if part_name.begins_with("Weapon_Flame"): + key = "Flame" + if not groups.has(key): + groups[key] = {} + for index: int in range(node.mesh.get_surface_count()): + var material: Material = presentation_material(node.get_active_material(index)) + if not groups[key].has(material): + var builder := SurfaceTool.new() + builder.begin(Mesh.PRIMITIVE_TRIANGLES) + groups[key][material] = builder + (groups[key][material] as SurfaceTool).append_from(node.mesh, index, transform) + for child: Node in node.get_children(): + if child is Node3D: + _collect_rig(child, transform, id, groups) + +func _collect(node: Node3D, parent_transform: Transform3D, surfaces: Dictionary) -> void: + var transform: Transform3D = parent_transform * node.transform + if node is MeshInstance3D and node.mesh != null: + for index: int in range(node.mesh.get_surface_count()): + var material: Material = presentation_material(node.get_active_material(index)) + if not surfaces.has(material): + var builder := SurfaceTool.new() + builder.begin(Mesh.PRIMITIVE_TRIANGLES) + surfaces[material] = builder + (surfaces[material] as SurfaceTool).append_from(node.mesh, index, transform) + for child: Node in node.get_children(): + if child is Node3D: + _collect(child, transform, surfaces) + +func presentation_material(source: Material) -> Material: + if source is StandardMaterial3D and (source.resource_name.begins_with("AB_") or source.resource_name.begins_with("BB_") or source.resource_name.begins_with("QG_") or source.resource_name.begins_with("FL_") or source.resource_name.begins_with("GB_")): + var ab_key: String = source.resource_name + if not _surface_materials.has(ab_key): + if source.emission_enabled or ab_key in ["AB_Lamp", "AB_Spark", "AB_Glass", "AB_Lens", "BB_Magma", "BB_Ember", "QG_Spring", "FL_Ember", "FL_Crystal", "GB_Crystal", "GB_Ember"]: + _surface_materials[ab_key] = source.duplicate() + else: + var ab := ShaderMaterial.new() + ab.shader = ArbeiterMaterial + ab.set_shader_parameter("roughness_value", source.roughness) + ab.set_shader_parameter("metallic_value", source.metallic) + var surface: int = 5 if source.metallic > .5 else 0 + if "Leather" in ab_key or "Boot" in ab_key or "Glove" in ab_key: + surface = 1 + elif "Cloth" in ab_key or "Hood" in ab_key: + surface = 2 + elif "Bark" in ab_key or "Wood" in ab_key or "Vine" in ab_key: + surface = 3 + elif "Leaf" in ab_key or "Moss" in ab_key or "Petal" in ab_key: + surface = 4 + ab.set_shader_parameter("surface_kind", surface) + ab.set_shader_parameter("grain_amount", .12 if surface in [0, 3] else .065) + ab.set_shader_parameter("grain_scale", 72.0 if surface in [0, 3] else 140.0) + ab.set_shader_parameter("relief_depth", .0009 if surface == 0 else (.0006 if surface == 3 else .00015)) + ab.resource_name = ab_key + _surface_materials[ab_key] = ab + return _surface_materials[ab_key] + if source is StandardMaterial3D and source.resource_name.begins_with("RB_") and source.resource_name != "RB_Cutwood" and not source.emission_enabled: + var key: String = source.resource_name + if not _surface_materials.has(key): + var material := ShaderMaterial.new() + material.shader = RingborkeMaterial + material.set_shader_parameter("wood_height",preload("res://assets/materials/phase10/oak-height-4k.png")) + material.set_shader_parameter("bark",key in ["RB_Bark","RB_Heartwood"]) + material.set_shader_parameter("endgrain",key == "RB_Cutwood") + material.set_shader_parameter("leaf",key in ["RB_Leaf","RB_Moss","RB_Petal"]) + _surface_materials[key] = material + return _surface_materials[key] + if source is StandardMaterial3D and source.resource_name.begins_with("SW_HD_Core_"): + var crystal_key: String = source.resource_name + if not _surface_materials.has(crystal_key): + var crystal := ShaderMaterial.new() + crystal.shader = PrismaticCore + crystal.set_shader_parameter("base_color", source.albedo_color) + _surface_materials[crystal_key] = crystal + return _surface_materials[crystal_key] + if not source is StandardMaterial3D or not source.resource_name.begins_with("SW_HD_") or source.emission_enabled: + return source + var key: String = source.resource_name + if not _surface_materials.has(key): + var material := ShaderMaterial.new() + material.shader = LivingMaterial if key.begins_with("SW_HD_W_") else ForgedMaterial + if key.begins_with("SW_HD_W_"): + material.set_shader_parameter("bark", "bark" in key or "wood" in key or "groove" in key) + material.set_shader_parameter("endgrain", "endgrain" in key) + material.set_shader_parameter("moss", "moss" in key) + material.set_shader_parameter("oak_color", load("res://assets/materials/phase10/oak-albedo-4k.png")) + material.set_shader_parameter("oak_height", load("res://assets/materials/phase10/oak-height-4k.png")) + material.set_shader_parameter("rock_map", preload("res://assets/materials/phase10/limestone-albedo.png")) + material.resource_name = key + material.set_shader_parameter("base_color", source.albedo_color) + material.set_shader_parameter("base_roughness", source.roughness) + material.set_shader_parameter("metalness", source.metallic) + material.set_shader_parameter("grain_amount", .17 if "basalt" in key or "edge" in key else .07) + _surface_materials[key] = material + return _surface_materials[key] + +func decorate_model(root: Node) -> void: + if root is MeshInstance3D and root.mesh != null: + for index: int in range(root.mesh.get_surface_count()): + root.set_surface_override_material(index, presentation_material(root.get_active_material(index))) + for child: Node in root.get_children(): + decorate_model(child) diff --git a/scripts/presentation/asset_library.gd.uid b/scripts/presentation/asset_library.gd.uid new file mode 100644 index 0000000..72bf1d7 --- /dev/null +++ b/scripts/presentation/asset_library.gd.uid @@ -0,0 +1 @@ +uid://d2g53kwjxkf3p diff --git a/scripts/presentation/enemy_visuals.gd b/scripts/presentation/enemy_visuals.gd new file mode 100644 index 0000000..0f7f057 --- /dev/null +++ b/scripts/presentation/enemy_visuals.gd @@ -0,0 +1,128 @@ +extends RefCounted +## Original rift creatures for the six enemy types used in the eight-wave slice. +## Generated once, then batched by material. They have no Phase 3 icon reference. + +static var _cache: Dictionary = {} + +static func create(data: Dictionary) -> Node3D: + var id: String = data.get("id", "") + if not id in ["e01", "e02", "e03", "e04", "e07", "e08"]: + return null + if not _cache.has(id): + var root := Node3D.new() + _build(root, id) + _cache[id] = AssetLibrary.bake_mesh(root) + root.free() + var result := MeshInstance3D.new() + result.name = "Rift_" + id + result.mesh = _cache[id] + return result + +static func _mat(hex: String, glow: bool = false) -> StandardMaterial3D: + var mat := StandardMaterial3D.new() + mat.albedo_color = Color(hex) + mat.roughness = 0.85 + mat.emission_enabled = glow + mat.emission = Color(hex) + mat.emission_energy_multiplier = 0.35 + return mat + +static func _piece(root: Node3D, at: Vector3, size: Vector3, mat: Material, box: bool = false) -> MeshInstance3D: + var instance := MeshInstance3D.new() + if box: + var mesh := BoxMesh.new() + mesh.size = size + instance.mesh = mesh + else: + var mesh := SphereMesh.new() + mesh.radius = 0.5 + mesh.height = 1.0 + mesh.radial_segments = 6 + mesh.rings = 2 + instance.mesh = mesh + instance.scale = size + instance.material_override = mat + instance.position = at + root.add_child(instance) + return instance + +static func _limb(root: Node3D, start: Vector3, end: Vector3, radius: float, mat: Material, tapered: bool = false) -> void: + var mesh := CylinderMesh.new() + mesh.height = start.distance_to(end) + mesh.bottom_radius = radius + mesh.top_radius = 0.0 if tapered else radius * 0.7 + mesh.radial_segments = 5 + var instance := MeshInstance3D.new() + instance.mesh = mesh + instance.material_override = mat + instance.position = (start + end) * 0.5 + instance.quaternion = Quaternion(Vector3.UP, (end - start).normalized()) + root.add_child(instance) + +static func _build(root: Node3D, id: String) -> void: + var dark := _mat("323e50") + var shell := _mat("869aa6") + var pale := _mat("d6dedc") + var rift := _mat("d27b94", true) + if id in ["e01", "e02"]: + var heavy: bool = id == "e02" + _piece(root, Vector3(0, .62, -.10), Vector3(1.12, .75 if heavy else .48, 1.15), dark) + _piece(root, Vector3(0, .91 if heavy else .74, -.18), Vector3(1.08, .68 if heavy else .35, 1.1), shell) + _piece(root, Vector3(0, .60, .54), Vector3(.60, .42, .48), dark) + for side: float in [-1.0, 1.0]: + for index: int in range(3): + var z: float = -.50 + index * .40 + var knee := Vector3(side * .73, .47, z + .10) + _limb(root, Vector3(side * .30, .62, z), knee, .12 if heavy else .07, shell) + _limb(root, knee, Vector3(side * .83, .04, z + .22), .075, dark, true) + _piece(root, Vector3(side * .16, .69, .74), Vector3(.11, .10, .08), rift) + _limb(root, Vector3(side * .22, .43, .65), Vector3(side * .40, .55, .92), .07, pale, true) + if heavy: + for z: float in [-.45, -.10, .25]: + _limb(root, Vector3(0, 1.00, z), Vector3(0, 1.42, z -.10), .14, pale, true) + elif id == "e03": + _piece(root, Vector3(0, 1.14, 0), Vector3(.60, .75, .48), dark) + _piece(root, Vector3(0, 1.58, .09), Vector3(.42, .59, .24), pale) + for side: float in [-1.0, 1.0]: + _piece(root, Vector3(side * .11, 1.61, .21), Vector3(.08, .15, .07), rift) + _limb(root, Vector3(side*.23,1.25,0), Vector3(side*.57,.95,.17), .12,shell) + _limb(root, Vector3(side*.57,.95,.17), Vector3(side*.68,1.29,.27), .09,pale,true) + for index: int in range(3): + var x: float = (index-1)*.22 + _limb(root,Vector3(x,1.0,0),Vector3(x-.12,.43,.04),.15,dark) + _limb(root,Vector3(x-.12,.43,.04),Vector3(x+.13,.05,.14),.09,shell,true) + elif id == "e04": + _piece(root, Vector3(0, 1.02, 0), Vector3(.42, .65, .35), dark) + _piece(root, Vector3(0, 1.54, .05), Vector3(.38, .43, .31), pale) + _piece(root, Vector3(0, 1.55, .23), Vector3(.23, .055, .05), rift, true) + for side: float in [-1.0,1.0]: + _limb(root,Vector3(side*.17,.88,0),Vector3(side*.28,.46,-.06),.10,shell) + _limb(root,Vector3(side*.28,.46,-.06),Vector3(side*.32,.03,.22),.07,dark) + _limb(root,Vector3(side*.20,1.23,0),Vector3(side*.46,1.07,.34),.07,shell) + _limb(root,Vector3(0,1.12,.45),Vector3(side*.61,1.15,.65),.06,pale) + _limb(root,Vector3(0,1.12,.20),Vector3(0,1.12,.94),.065,rift,true) + elif id == "e07": + _piece(root, Vector3(0, 1.03, -.22), Vector3(.90, .88, 1.37), dark) + _piece(root, Vector3(0, 1.61, .39), Vector3(.66, .85, .71), shell) + _piece(root, Vector3(0, 1.62, .82), Vector3(.38, .31, .51), pale) + for side: float in [-1.0,1.0]: + for z: float in [-.65,.35]: + _limb(root,Vector3(side*.29,.91,z),Vector3(side*.42,.09,z+.08),.14,dark) + _piece(root,Vector3(side*.42,.09,z+.13),Vector3(.27,.17,.31),pale,true) + _piece(root,Vector3(side*.25,1.78,.67),Vector3(.10,.10,.14),rift) + _limb(root,Vector3(side*.22,1.89,.40),Vector3(side*.64,2.46,.10),.11,pale,true) + _limb(root,Vector3(side*.45,2.17,.24),Vector3(side*.89,2.39,.40),.08,pale,true) + _limb(root,Vector3(side*.54,2.29,.17),Vector3(side*.52,2.61,.40),.06,pale,true) + else: + _piece(root,Vector3(0,1.07,0),Vector3(1.03,1.32,.66),dark,true) + _piece(root,Vector3(0,1.23,.37),Vector3(.69,.91,.17),shell,true) + _piece(root,Vector3(0,1.26,.48),Vector3(.11,.70,.06),rift,true) + _piece(root,Vector3(0,1.98,.08),Vector3(.52,.44,.46),pale,true) + _piece(root,Vector3(0,1.99,.32),Vector3(.35,.08,.05),rift,true) + for side: float in [-1.0,1.0]: + _piece(root,Vector3(side*.38,.29,0),Vector3(.40,.59,.49),shell,true) + _piece(root,Vector3(side*.39,.09,.20),Vector3(.48,.17,.64),dark,true) + _piece(root,Vector3(side*.78,1.22,.03),Vector3(.42,1.13,.55),shell,true) + for index: int in range(2): + _piece(root,Vector3(side*.78,1.89,-.14+index*.34),Vector3(.42,.24,.16),pale,true) + _limb(root,Vector3(side*.76,.99,.34),Vector3(side*.80,.90,.97),.13,dark) diff --git a/scripts/presentation/enemy_visuals.gd.uid b/scripts/presentation/enemy_visuals.gd.uid new file mode 100644 index 0000000..2f68638 --- /dev/null +++ b/scripts/presentation/enemy_visuals.gd.uid @@ -0,0 +1 @@ +uid://dwn54hcemwno8 diff --git a/scripts/presentation/forged_material.gdshader b/scripts/presentation/forged_material.gdshader new file mode 100644 index 0000000..d0760b2 --- /dev/null +++ b/scripts/presentation/forged_material.gdshader @@ -0,0 +1,48 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; + +uniform vec4 base_color : source_color = vec4(.28,.29,.31,1.0); +uniform float metalness = 0.0; +uniform float base_roughness = .78; +uniform float grain_amount = .08; +uniform sampler2D rock_map : source_color, filter_linear_mipmap_anisotropic, repeat_enable; +varying vec3 local_position; +varying vec3 local_normal; + +float hash3(vec3 p) { + p = fract(p * .1031); + p += dot(p, p.yzx + 33.33); + return fract((p.x + p.y) * p.z); +} +float noise3(vec3 p) { + vec3 i = floor(p); + vec3 f = fract(p); + f = f*f*(3.0-2.0*f); + return mix(mix(mix(hash3(i),hash3(i+vec3(1,0,0)),f.x),mix(hash3(i+vec3(0,1,0)),hash3(i+vec3(1,1,0)),f.x),f.y), + mix(mix(hash3(i+vec3(0,0,1)),hash3(i+vec3(1,0,1)),f.x),mix(hash3(i+vec3(0,1,1)),hash3(i+vec3(1,1,1)),f.x),f.y),f.z); +} +void vertex() { + local_position = VERTEX; + local_normal = NORMAL; +} +void fragment() { + float veins = noise3(local_position * 16.0); + float grain = noise3(local_position * 100.0); + float detail_fade = 1.0-smoothstep(.008,.03,length(fwidth(local_position))); + grain = mix(.5,grain,detail_fade); + float weather = smoothstep(.40,.62,veins); + ALBEDO = base_color.rgb * (1.0 - grain_amount + weather * grain_amount * 1.2); + vec3 w=pow(abs(local_normal),vec3(5.0)); w/=max(dot(w,vec3(1.0)),.0001); + vec3 p=local_position*1.5; + vec3 rock=texture(rock_map,p.xy).rgb*w.z+texture(rock_map,p.xz).rgb*w.y+texture(rock_map,p.zy).rgb*w.x; + if(metalness < .25) { ALBEDO *= .64 + rock*1.45; grain = dot(rock,vec3(.333)); } + ROUGHNESS = clamp(base_roughness + (grain-.5)*grain_amount, .15, .95); + METALLIC = metalness; + // Sparse pits affect fine normal response while all large detail is geometry. + vec3 n = NORMAL; + vec3 dpdx = dFdx(VERTEX), dpdy = dFdy(VERTEX); + vec3 rx = cross(dpdy,n), ry = cross(n,dpdx); + float determinant = dot(dpdx,rx); + vec3 gradient = (dFdx(grain)*rx + dFdy(grain)*ry); + NORMAL = normalize(abs(determinant)*n - sign(determinant)*gradient*grain_amount*.012); +} diff --git a/scripts/presentation/forged_material.gdshader.uid b/scripts/presentation/forged_material.gdshader.uid new file mode 100644 index 0000000..db7d509 --- /dev/null +++ b/scripts/presentation/forged_material.gdshader.uid @@ -0,0 +1 @@ +uid://d0cv678sdvpvu diff --git a/scripts/presentation/lighting.gd b/scripts/presentation/lighting.gd new file mode 100644 index 0000000..c7b8538 --- /dev/null +++ b/scripts/presentation/lighting.gd @@ -0,0 +1,50 @@ +extends RefCounted +## Shared cinematic lighting for game and inspection studio. + +static func configure(environment: Environment, studio: bool = false) -> void: + environment.background_mode = Environment.BG_SKY + environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR + environment.ambient_light_color = Color("a8b4c8") + environment.ambient_light_energy = .28 if studio else .34 + environment.reflected_light_source = Environment.REFLECTION_SOURCE_SKY + var sky := Sky.new() + var material := ProceduralSkyMaterial.new() + material.sky_top_color = Color("2a3d58") if not studio else Color("1a2434") + material.sky_horizon_color = Color("e8c9a0") if not studio else Color("3a4a58") + material.ground_bottom_color = Color("1a1c24") + material.ground_horizon_color = Color("6a7a78") + material.sky_energy_multiplier = 1.05 if not studio else .7 + material.ground_energy_multiplier = .4 + material.sun_angle_max = 28.0 + material.sun_curve = .12 + sky.sky_material = material + environment.sky = sky + environment.tonemap_mode = Environment.TONE_MAPPER_ACES + environment.tonemap_exposure = 1.0 + environment.tonemap_white = 4.0 + environment.adjustment_enabled = true + environment.adjustment_brightness = 1.0 + environment.adjustment_contrast = 1.06 if studio else 1.12 + environment.adjustment_saturation = 1.05 if studio else 1.18 + if not studio: + environment.fog_enabled = true + environment.fog_light_color = Color("7a9aaa") + environment.fog_density = .0022 + environment.fog_sky_affect = .25 + environment.volumetric_fog_enabled = false + if RenderingServer.get_current_rendering_method() == "forward_plus": + environment.ssao_enabled = true + environment.ssao_radius = 1.1 + environment.ssao_intensity = 2.2 + environment.ssao_power = 1.15 + environment.ssao_detail = .4 + environment.glow_enabled = true + environment.glow_intensity = .55 + environment.glow_strength = .85 + environment.glow_hdr_threshold = 1.2 + environment.glow_bloom = .05 + environment.glow_blend_mode = Environment.GLOW_BLEND_MODE_SCREEN + for i in range(1, 5): + environment.set_glow_level(i, .4 if i < 3 else .15) + environment.sdfgi_enabled = false + environment.ssr_enabled = false diff --git a/scripts/presentation/lighting.gd.uid b/scripts/presentation/lighting.gd.uid new file mode 100644 index 0000000..6042ea0 --- /dev/null +++ b/scripts/presentation/lighting.gd.uid @@ -0,0 +1 @@ +uid://dsck7jub2dr2d diff --git a/scripts/presentation/living_material.gdshader b/scripts/presentation/living_material.gdshader new file mode 100644 index 0000000..d0f81a3 --- /dev/null +++ b/scripts/presentation/living_material.gdshader @@ -0,0 +1,55 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; +uniform vec4 base_color : source_color; +uniform float base_roughness = .85; +uniform bool bark = false; +uniform bool endgrain = false; +uniform bool moss = false; +uniform sampler2D oak_color : source_color, filter_linear_mipmap_anisotropic, repeat_enable; +uniform sampler2D oak_height : filter_linear_mipmap_anisotropic, repeat_enable; +varying vec3 position_model; +varying vec3 local_normal; +float hash(vec3 p) { p=fract(p*.1031); p+=dot(p,p.yzx+33.33); return fract((p.x+p.y)*p.z); } +float noise(vec3 p) { + vec3 i=floor(p),f=fract(p); f=f*f*(3.0-2.0*f); + return mix(mix(mix(hash(i),hash(i+vec3(1,0,0)),f.x),mix(hash(i+vec3(0,1,0)),hash(i+vec3(1,1,0)),f.x),f.y),mix(mix(hash(i+vec3(0,0,1)),hash(i+vec3(1,0,1)),f.x),mix(hash(i+vec3(0,1,1)),hash(i+vec3(1,1,1)),f.x),f.y),f.z); +} +void vertex() { position_model=VERTEX; local_normal=NORMAL; } +void fragment() { + vec3 p=position_model; + float mottling=noise(p*15.0); + float detail=noise(p*(bark ? vec3(105.0,12.0,105.0) : vec3(70.0))); + float fade=1.0-smoothstep(.005,.025,length(fwidth(p))); + detail=mix(.5,detail,fade); + float fissure=bark ? smoothstep(.36,.50,detail) : detail; + ALBEDO=base_color.rgb*mix(.64,1.04,mottling)*mix(.72,1.0,fissure); + if(bark) { + vec3 w=pow(abs(local_normal),vec3(6.0)); w/=max(dot(w,vec3(1)),.0001); + vec3 q=p*vec3(1.3,.72,1.3); + vec3 oak=texture(oak_color,q.zy).rgb*w.x+texture(oak_color,q.xz).rgb*w.y+texture(oak_color,q.xy).rgb*w.z; + detail=texture(oak_height,q.zy).r*w.x+texture(oak_height,q.xz).r*w.y+texture(oak_height,q.xy).r*w.z; + ALBEDO=base_color.rgb*(.60+oak*2.0); + } else { + ALBEDO=base_color.rgb*mix(.78,1.12,mottling); + BACKLIGHT=base_color.rgb*.20; + } + if(moss) { + float carpet=noise(p*48.0)*.6+noise(p*11.0)*.4; + ALBEDO=base_color.rgb*mix(.60,1.2,carpet); + detail=carpet; + } + if(endgrain) { + vec2 q=UV-vec2(.5); float a=atan(q.y,q.x); + float radius=length(q)*(1.0+.03*sin(a*3.0)+.02*cos(a*7.0)); + float rings=sin(radius*210.0+sin(a*9.0)*.13)*.5+.5; + ALBEDO=base_color.rgb*mix(.76,1.08,rings)*mix(.90,1.03,noise(vec3(UV*150.0,0.0))); + detail=rings; + } + ROUGHNESS=clamp(base_roughness+(detail-.5)*.20,.5,1.0); + METALLIC=0.0; + vec3 n=NORMAL,dx=dFdx(VERTEX),dy=dFdy(VERTEX); + vec3 rx=cross(dy,n),ry=cross(n,dx); + float det=dot(dx,rx); + vec3 gradient=dFdx(detail)*rx+dFdy(detail)*ry; + NORMAL=normalize(abs(det)*n-sign(det)*gradient*(bark ? .006 : .0003)); +} diff --git a/scripts/presentation/living_material.gdshader.uid b/scripts/presentation/living_material.gdshader.uid new file mode 100644 index 0000000..e4d6ba7 --- /dev/null +++ b/scripts/presentation/living_material.gdshader.uid @@ -0,0 +1 @@ +uid://b4i87do1aosjo diff --git a/scripts/presentation/menu_stage.gd b/scripts/presentation/menu_stage.gd new file mode 100644 index 0000000..f8b955a --- /dev/null +++ b/scripts/presentation/menu_stage.gd @@ -0,0 +1,332 @@ +extends Node3D +## Menu diorama in its own World3D: two banks of the Kluft, a Saumkern dais per Bund, +## real game models in their idle clips. No battle units and no GameState writes; +## the main menu owns shots, visibility and whether this stage renders at all. +signal formation_ready(faction: String) + +const Lighting = preload("res://scripts/presentation/lighting.gd") +const Sanctuary = preload("res://scripts/presentation/sanctuary.gd") +const RiverMaterial = preload("res://scripts/presentation/river.gdshader") +const DIORAMA := "res://assets/environment/menu-stage.glb" +const MANIFEST := "res://assets/menu_stage_manifest.json" +# Slots on each dais as [id, across the shot, towards the camera] so no guardian hides another. +const SETUPS: Dictionary = { + "glutpakt": {"core": "core_team1", "accent": Color("ff8a44"), + "figures": [["g06", -.15, .55], ["g04", -1.95, -.35], ["g05", 1.75, -.05]]}, + "wurzelbund": {"core": "core_team0", "accent": Color("6fe0c0"), + "figures": [["w04", -.1, .35], ["w10", 1.85, -.2], ["w06", -1.95, -.25]]}, +} +# Title shot: [position, look target]; the misty lower left carries the title block. +const TITLE_SHOT: Array = [Vector3(-8.6, 4.3, 10.2), Vector3(4.6, .4, -5.2)] +# Bund shots orbit the dais: azimuth (rad), distance, height, and a yaw that moves the +# formation to the right of the setup panel. Subjects stay whole on 16:10 to 21:9. +const BUND_SHOTS: Dictionary = { + "wurzelbund": {"azimuth": 2.05, "distance": 10.2, "height": 2.9, "yaw": .21}, + "glutpakt": {"azimuth": 2.2, "distance": 10.4, "height": 3.0, "yaw": .21}, +} +var SHOTS: Dictionary = {} +var camera: Camera3D +var reduced_motion: bool = false +var figures: Dictionary = {"glutpakt": [], "wurzelbund": []} +var daises: Dictionary = {} +var _time: float = 0.0 +var _pending: Dictionary = {} +var _particles: Array[GPUParticles3D] = [] +var _flicker: Array[OmniLight3D] = [] +var _shot_from: Transform3D +var _shot_to: Transform3D +var _shot_t: float = 1.0 +var _shot_length: float = 1.4 +var _shot_name: String = "" + +func _ready() -> void: + name = "MenuStage" + var manifest: Variant = JSON.parse_string(FileAccess.get_file_as_string(MANIFEST)) + daises = manifest.get("daises", {}) if manifest is Dictionary else {} + SHOTS["title"] = TITLE_SHOT + for faction: String in BUND_SHOTS: + var dais: Dictionary = daises.get(faction, {}) + var centre := Vector3(dais.center[0], dais.center[1], dais.center[2]) if dais.has("center") else Vector3.ZERO + var shot: Dictionary = BUND_SHOTS[faction] + var subject := centre + Vector3(0, 1.0, 0) + var eye := centre + Vector3(cos(shot.azimuth), 0, sin(shot.azimuth)) * float(shot.distance) + Vector3(0, shot.height, 0) + var view: Vector3 = (subject - eye).normalized().rotated(Vector3.UP, float(shot.yaw)) + SHOTS[faction] = [eye, eye + view * float(shot.distance)] + var diorama: Node3D = (load(DIORAMA) as PackedScene).instantiate() + add_child(diorama) + _decorate(diorama, {}) + _river() + _environment() + for faction: String in SETUPS: + _place_core(faction) + _request(faction) + _lights() + camera = Camera3D.new() + camera.fov = 33.0 + camera.near = .1 + camera.far = 220.0 + add_child(camera) + camera.current = true + set_shot_named("title", true) + +func _decorate(node: Node, cache: Dictionary) -> void: + if node is MeshInstance3D: + for surface: int in range(node.mesh.get_surface_count()): + var source := node.mesh.surface_get_material(surface) as StandardMaterial3D + if source == null: + continue + var key: String = source.resource_name + # Emissive and metallic accents keep their authored GLB material. + if key.contains("ember") or key.contains("spring") or key.contains("teal") or key.contains("coral") or key.contains("brass"): + continue + if not cache.has(key): + cache[key] = Sanctuary.terrain_material(source) + node.set_surface_override_material(surface, cache[key]) + for child: Node in node.get_children(): + _decorate(child, cache) + +func _river() -> void: + var river := MeshInstance3D.new() + var plane := PlaneMesh.new() + plane.size = Vector2(90, 140) + river.mesh = plane + river.position = Vector3(-6, -13.5, -12) + var water := ShaderMaterial.new() + water.shader = RiverMaterial + river.material_override = water + add_child(river) + +func _environment() -> void: + var environment := WorldEnvironment.new() + var settings := Environment.new() + Lighting.configure(settings) + var sky: ProceduralSkyMaterial = settings.sky.sky_material + sky.sky_top_color = Color("0e1830") + sky.sky_horizon_color = Color("b9785a") + sky.ground_horizon_color = Color("2a3434") + sky.ground_bottom_color = Color("0c1014") + sky.sky_energy_multiplier = .8 + settings.ambient_light_color = Color("7d8ea8") + settings.ambient_light_energy = .18 + settings.fog_enabled = true + settings.fog_light_color = Color("5f7382") + settings.fog_density = .014 + settings.fog_sky_affect = .45 + settings.fog_height = -2.0 + settings.fog_height_density = .35 + settings.adjustment_saturation = 1.08 + environment.environment = settings + var attributes := CameraAttributesPractical.new() + attributes.dof_blur_far_enabled = true + attributes.dof_blur_far_distance = 19.0 + attributes.dof_blur_far_transition = 16.0 + attributes.dof_blur_amount = .05 + environment.camera_attributes = attributes + add_child(environment) + +func _lights() -> void: + # Low evening key from behind the far bank rims the figures; cool fill from the viewer. + _directional(Vector3(-22, 158, 0), Color("ffc38a"), 2.1, true) + _directional(Vector3(-28, 30, 0), Color("93aad4"), .34, false) + _directional(Vector3(-60, -70, 0), Color("ffe0bc"), .22, false) + var glut: Dictionary = daises.get("glutpakt", {}) + for point: Array in glut.get("braziers", []): + var ember := _omni(Vector3(point[0], point[1], point[2]), Color("ff8a3c"), 1.5, 4.5) + _flicker.append(ember) + _sparks(Vector3(point[0], point[1] - .1, point[2])) + var root: Dictionary = daises.get("wurzelbund", {}) + if root.has("spring"): + var spring: Array = root.spring + _omni(Vector3(spring[0], spring[1] + .4, spring[2]), Color("6fe0c0"), 1.3, 4.0) + _pollen(Vector3(spring[0] + 2.0, 1.2, spring[2] + 1.0)) + +func _directional(rotation_deg: Vector3, color: Color, energy: float, shadow: bool) -> void: + var light := DirectionalLight3D.new() + light.rotation_degrees = rotation_deg + light.light_color = color + light.light_energy = energy + light.shadow_enabled = shadow + light.light_angular_distance = 1.4 + if shadow: + light.directional_shadow_max_distance = 34.0 + light.shadow_blur = 1.5 + add_child(light) + +func _omni(at: Vector3, color: Color, energy: float, range_value: float) -> OmniLight3D: + var light := OmniLight3D.new() + light.position = at + light.light_color = color + light.light_energy = energy + light.omni_range = range_value + light.omni_attenuation = 1.4 + light.set_meta("energy", energy) + add_child(light) + return light + +func _place_core(faction: String) -> void: + var setup: Dictionary = SETUPS[faction] + var dais: Dictionary = daises.get(faction, {}) + if not dais.has("core"): + return + var at := Vector3(dais.core[0], dais.core[1], dais.core[2]) + var core: Node3D = AssetLibrary.instantiate_fighter(setup.core) + if core != null: + core.position = at + add_child(core) + if core.has_method("trigger_activate"): + core.trigger_activate() + core.set_meta("stage_core", true) + figures[faction].append(core) + _omni(at + Vector3(0, 1.7, .2), setup.accent, 1.5, 5.5) + +func _request(faction: String) -> void: + for entry: Array in SETUPS[faction].figures: + var path: String = str(AssetLibrary._models.get(entry[0], {}).get("resource_path", "")) + if not path.is_empty() and not ResourceLoader.has_cached(path) and not _pending.has(path): + ResourceLoader.load_threaded_request(path) + _pending[path] = faction + _try_finish(faction) + +func _try_finish(faction: String) -> void: + if is_ready(faction): + return + for path: String in _pending: + if _pending[path] == faction: + return + var dais: Dictionary = daises.get(faction, {}) + var center := Vector3(dais.center[0], dais.center[1], dais.center[2]) if dais.has("center") else Vector3.ZERO + var look: Vector3 = SHOTS[faction][0] + var towards := Vector3(look.x - center.x, 0, look.z - center.z).normalized() + var across := Vector3(-towards.z, 0, towards.x) + for entry: Array in SETUPS[faction].figures: + var figure: Node3D = AssetLibrary.instantiate_fighter(entry[0]) + if figure == null: + continue + figure.position = center + across * float(entry[1]) + towards * float(entry[2]) + # Turn each guardian partly towards its own camera shot. + figure.rotation.y = atan2(look.x - figure.position.x, look.z - figure.position.z) * .55 + figure.set_meta("phase", figures[faction].size() * .73) + figure.set_meta("rest", figure.position) + add_child(figure) + figures[faction].append(figure) + set_meta("ready_" + faction, true) + formation_ready.emit(faction) + +func is_ready(faction: String) -> bool: + return has_meta("ready_" + faction) + +func set_shot_named(shot: String, instant: bool = false) -> void: + if not SHOTS.has(shot): + return + _shot_name = shot + var entry: Array = SHOTS[shot] + set_shot(Transform3D(Basis.looking_at(entry[1] - entry[0], Vector3.UP), entry[0]), instant) + +func current_shot() -> String: + return _shot_name + +func set_shot(target: Transform3D, instant: bool) -> void: + if instant or reduced_motion or not is_inside_tree(): + camera.transform = target + _shot_to = target + _shot_t = 1.0 + return + _shot_from = camera.transform + _shot_to = target + _shot_t = 0.0 + +func is_moving() -> bool: + return _shot_t < 1.0 + +func set_reduced_motion(value: bool) -> void: + reduced_motion = value + for particles: GPUParticles3D in _particles: + particles.emitting = not value + particles.visible = not value + if value: + set_shot(_shot_to, true) + +func _process(delta: float) -> void: + for path: String in _pending.keys(): + var status: int = ResourceLoader.load_threaded_get_status(path) + if status != ResourceLoader.THREAD_LOAD_IN_PROGRESS: + if status == ResourceLoader.THREAD_LOAD_LOADED: + ResourceLoader.load_threaded_get(path) + var faction: String = _pending[path] + _pending.erase(path) + _try_finish(faction) + _time += delta + var motion: float = .4 if reduced_motion else 1.0 + for faction: String in figures: + for figure: Node3D in figures[faction]: + var phase: float = float(figure.get_meta("phase", 0.0)) + if figure.has_meta("stage_core"): + figure.pose(_time * motion, false, 0, 0, 0, delta) + elif figure.has_method("update_combat"): + figure.preview("idle", fmod(_time * motion + phase, figure.clip_length("idle"))) + else: + # Rigid HD figures: a slow breath on the whole node, never the shared meshes. + var rest: Vector3 = figure.get_meta("rest") + figure.position = rest + Vector3(0, sin((_time + phase) * 1.7) * .012 * motion, 0) + for light: OmniLight3D in _flicker: + var base: float = float(light.get_meta("energy")) + light.light_energy = base if reduced_motion else base * (1.0 + .08 * sin(_time * 7.3 + light.position.x) + .05 * sin(_time * 13.1)) + if _shot_t < 1.0: + _shot_t = minf(1.0, _shot_t + delta / _shot_length) + var eased: float = _shot_t * _shot_t * (3.0 - 2.0 * _shot_t) + camera.transform = _shot_from.interpolate_with(_shot_to, eased) + elif not reduced_motion: + # Barely perceptible breathing of the frame; never a travelling shot. + var sway := Vector3(sin(_time * .21) * .05, sin(_time * .17) * .03, 0) + camera.transform = Transform3D(_shot_to.basis, _shot_to.origin + _shot_to.basis * sway) + +func _particle_system(origin: Vector3, amount: int, lifetime: float, extents: Vector3, gravity: Vector3, color: Color, size: Vector2, energy: float) -> GPUParticles3D: + var particles := GPUParticles3D.new() + particles.amount = amount + particles.lifetime = lifetime + particles.preprocess = lifetime + particles.position = origin + particles.visibility_aabb = AABB(-extents - Vector3(1, 1, 1), extents * 2 + Vector3(2, 6, 2)) + var motion := ParticleProcessMaterial.new() + motion.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX + motion.emission_box_extents = extents + motion.gravity = gravity + motion.initial_velocity_min = .02 + motion.initial_velocity_max = .12 + motion.turbulence_enabled = true + motion.turbulence_noise_strength = .4 + motion.turbulence_noise_scale = 2.2 + motion.scale_min = size.x + motion.scale_max = size.y + var fade := Gradient.new() + fade.set_color(0, Color(1, 1, 1, 0)) + fade.add_point(.25, Color(1, 1, 1, 1)) + fade.set_color(fade.get_point_count() - 1, Color(1, 1, 1, 0)) + var ramp := GradientTexture1D.new() + ramp.gradient = fade + motion.color_ramp = ramp + particles.process_material = motion + var mote := SphereMesh.new() + mote.radius = 1 + mote.height = 2 + mote.radial_segments = 6 + mote.rings = 3 + var glow := StandardMaterial3D.new() + glow.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + glow.vertex_color_use_as_albedo = true + glow.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA + glow.albedo_color = color + glow.emission_enabled = true + glow.emission = color + glow.emission_energy_multiplier = energy + mote.material = glow + particles.draw_pass_1 = mote + add_child(particles) + _particles.append(particles) + return particles + +func _sparks(origin: Vector3) -> void: + _particle_system(origin, 18, 2.6, Vector3(.22, .05, .22), Vector3(0, .55, 0), Color("ffb060"), Vector2(.010, .022), 3.0) + +func _pollen(origin: Vector3) -> void: + _particle_system(origin, 36, 8.0, Vector3(3.2, 1.2, 2.4), Vector3(.03, .04, 0), Color("c8f0b0"), Vector2(.012, .024), 1.6) diff --git a/scripts/presentation/menu_stage.gd.uid b/scripts/presentation/menu_stage.gd.uid new file mode 100644 index 0000000..fd9cbd0 --- /dev/null +++ b/scripts/presentation/menu_stage.gd.uid @@ -0,0 +1 @@ +uid://0qjdv7dxk76x diff --git a/scripts/presentation/prismatic_core.gdshader b/scripts/presentation/prismatic_core.gdshader new file mode 100644 index 0000000..aac5654 --- /dev/null +++ b/scripts/presentation/prismatic_core.gdshader @@ -0,0 +1,14 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; +uniform vec4 base_color : source_color = vec4(.24,.8,.7,1.0); +varying vec3 local; +void vertex() { local=VERTEX; } +void fragment() { + float fresnel=pow(1.0-clamp(dot(normalize(NORMAL),normalize(VIEW)),0.0,1.0),3.0); + float facet=sin(local.y*18.0+local.x*5.0+local.z*7.0)*.5+.5; + float heart=exp(-length(local.xz)*3.0)*(.75+.08*sin(TIME*1.3)); + ALBEDO=base_color.rgb*mix(.25,.80,facet)+vec3(.15,.23,.20)*fresnel; + METALLIC=.35; + ROUGHNESS=.16; + EMISSION=base_color.rgb*(heart*.65+fresnel*.7); +} diff --git a/scripts/presentation/prismatic_core.gdshader.uid b/scripts/presentation/prismatic_core.gdshader.uid new file mode 100644 index 0000000..682501b --- /dev/null +++ b/scripts/presentation/prismatic_core.gdshader.uid @@ -0,0 +1 @@ +uid://c6u8ycut3joq6 diff --git a/scripts/presentation/ringborke.gdshader b/scripts/presentation/ringborke.gdshader new file mode 100644 index 0000000..b4ebe07 --- /dev/null +++ b/scripts/presentation/ringborke.gdshader @@ -0,0 +1,34 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; +uniform sampler2D wood_height : filter_linear_mipmap_anisotropic, repeat_enable; +uniform bool bark = false; +uniform bool leaf = false; +uniform bool endgrain = false; +void fragment() { + float h = texture(wood_height, UV).r; + ALBEDO = COLOR.rgb * (bark ? mix(.48,.85,h) : .80); + if (endgrain) { + vec2 p=(UV-vec2(.5))*2.0; + float a=atan(p.y,p.x), r=length(p); + float phase=r*12.0+.13*sin(a*3.0+r*9.0)+.07*sin(a*7.0-r*8.0); + float edge=abs(sin(phase*3.1415926)); + float line=1.0-smoothstep(.12,.28+length(fwidth(p))*45.0,edge); + float fibres=sin(a*113.0+r*38.0)*sin(r*290.0+a*5.0); + float split=0.0; + for(int k=0;k<3;k++) { + float ca=.36+float(k)*2.12; + float dist=abs(atan(sin(a-ca-.012*sin(r*24.0)),cos(a-ca-.012*sin(r*24.0)))); + split=max(split,(1.0-smoothstep(.003,.014,dist))*smoothstep(.48+.1*float(k),.91,r)); + } + ALBEDO=vec3(.265,.147,.066)*mix(1.20,.56,line)*(1.0+fibres*.07)*mix(1.0,.20,split); + ROUGHNESS=.86; + } + ROUGHNESS = bark ? mix(.74,.96,h) : .84; + if (leaf) { BACKLIGHT = COLOR.rgb*.22; } + if (bark) { + vec3 dx=dFdx(VERTEX), dy=dFdy(VERTEX), n=NORMAL; + vec3 rx=cross(dy,n), ry=cross(n,dx); + float det=dot(dx,rx); + NORMAL=normalize(abs(det)*n-sign(det)*(dFdx(h)*rx+dFdy(h)*ry)*.0018); + } +} diff --git a/scripts/presentation/ringborke.gdshader.uid b/scripts/presentation/ringborke.gdshader.uid new file mode 100644 index 0000000..a8b1004 --- /dev/null +++ b/scripts/presentation/ringborke.gdshader.uid @@ -0,0 +1 @@ +uid://cshnyuqbsfafr diff --git a/scripts/presentation/river.gdshader b/scripts/presentation/river.gdshader new file mode 100644 index 0000000..acc4b79 --- /dev/null +++ b/scripts/presentation/river.gdshader @@ -0,0 +1,22 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; +varying vec3 world; +float hash(vec2 p) { return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453); } +float noise(vec2 p) { + vec2 i=floor(p),f=fract(p); f=f*f*(3.0-2.0*f); + return mix(mix(hash(i),hash(i+vec2(1,0)),f.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),f.x),f.y); +} +void vertex() { + world=(MODEL_MATRIX*vec4(VERTEX,1.0)).xyz; +} +void fragment() { + vec2 flow=world.xz*.75+vec2(TIME*.037,-TIME*.075); + float waves=noise(flow)*.6+noise(flow*2.13+vec2(-TIME*.06,0))*.3+noise(flow*4.17)*.1; + float fresnel=pow(1.0-clamp(dot(normalize(NORMAL),normalize(VIEW)),0.0,1.0),4.0); + ALBEDO=mix(vec3(.022,.094,.098),vec3(.042,.145,.15),waves)+vec3(.045,.07,.075)*fresnel; + ROUGHNESS=.32; + METALLIC=.18; + vec3 n=NORMAL,dx=dFdx(VERTEX),dy=dFdy(VERTEX); + vec3 rx=cross(dy,n),ry=cross(n,dx);float det=dot(dx,rx); + NORMAL=normalize(abs(det)*n-sign(det)*(dFdx(waves)*rx+dFdy(waves)*ry)*.055); +} diff --git a/scripts/presentation/river.gdshader.uid b/scripts/presentation/river.gdshader.uid new file mode 100644 index 0000000..dad703a --- /dev/null +++ b/scripts/presentation/river.gdshader.uid @@ -0,0 +1 @@ +uid://bu7axpfu1qd4d diff --git a/scripts/presentation/sanctuary.gd b/scripts/presentation/sanctuary.gd new file mode 100644 index 0000000..b524805 --- /dev/null +++ b/scripts/presentation/sanctuary.gd @@ -0,0 +1,81 @@ +extends Node3D +## The environment has no colliders: board coordinates remain the gameplay source. +const TerrainMaterial = preload("res://scripts/presentation/sanctuary.gdshader") +const WaterMaterial = preload("res://scripts/presentation/river.gdshader") +const Stone = preload("res://assets/materials/phase10/limestone-albedo.png") +var _materials: Dictionary = {} + +func _ready() -> void: + name = "VerdantRift" + var landscape: Node3D = preload("res://assets/environment/verdant-rift.glb").instantiate() + add_child(landscape) + _decorate(landscape) + var river := MeshInstance3D.new() + river.name = "LivingRiver" + var surface := PlaneMesh.new() + surface.size = Vector2(180.0, 180.0) + surface.subdivide_width = 1 + surface.subdivide_depth = 1 + river.mesh = surface + river.position.y = -3.7 + var water := ShaderMaterial.new() + water.shader = WaterMaterial + river.material_override = water + add_child(river) + # The embers are deliberately sparse and never cover board cell indicators. + var motes := GPUParticles3D.new() + motes.name = "SanctuaryMotes" + motes.amount = 75 + motes.lifetime = 12 + motes.visibility_aabb = AABB(Vector3(-32,-5,-34), Vector3(64,18,68)) + var motion := ParticleProcessMaterial.new() + motion.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_BOX + motion.emission_box_extents = Vector3(24,1,28) + motion.gravity = Vector3(.02,.045,.015) + motion.initial_velocity_min = .01 + motion.initial_velocity_max = .12 + motion.scale_min = .013 + motion.scale_max = .035 + motes.process_material = motion + var mote := SphereMesh.new() + mote.radius = 1 + mote.height = 2 + mote.radial_segments = 6 + mote.rings = 3 + var light := StandardMaterial3D.new() + light.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + light.albedo_color = Color("c6d7a0") + light.emission_enabled = true + light.emission = Color("b3c985") + light.emission_energy_multiplier = 1.5 + mote.material = light + motes.draw_pass_1 = mote + add_child(motes) + +func _decorate(node: Node) -> void: + if node is MeshInstance3D: + for surface: int in range(node.mesh.get_surface_count()): + var source: StandardMaterial3D = node.mesh.surface_get_material(surface) + if source == null: + continue + var key: String = source.resource_name + if "teal" in key or "coral" in key or "brass" in key: + continue + if not _materials.has(key): + _materials[key] = terrain_material(source) + node.set_surface_override_material(surface, _materials[key]) + for child: Node in node.get_children(): + _decorate(child) + +## Shared Kluft surface for ENV_* materials; also used by the menu diorama. +static func terrain_material(source: StandardMaterial3D) -> ShaderMaterial: + var key: String = source.resource_name + var material := ShaderMaterial.new() + material.shader = TerrainMaterial + material.set_shader_parameter("base_color", source.albedo_color) + material.set_shader_parameter("stone_map", Stone) + material.set_shader_parameter("foliage", "leaf" in key) + material.set_shader_parameter("bark", "bark" in key) + material.set_shader_parameter("soil", "soil" in key) + material.set_shader_parameter("paving", "paving" in key) + return material diff --git a/scripts/presentation/sanctuary.gd.uid b/scripts/presentation/sanctuary.gd.uid new file mode 100644 index 0000000..29b022a --- /dev/null +++ b/scripts/presentation/sanctuary.gd.uid @@ -0,0 +1 @@ +uid://bm8xgo0a06pf5 diff --git a/scripts/presentation/sanctuary.gdshader b/scripts/presentation/sanctuary.gdshader new file mode 100644 index 0000000..bf0abc9 --- /dev/null +++ b/scripts/presentation/sanctuary.gdshader @@ -0,0 +1,52 @@ +shader_type spatial; +render_mode diffuse_burley, specular_schlick_ggx; +uniform vec4 base_color : source_color; +uniform sampler2D stone_map : source_color, filter_linear_mipmap_anisotropic, repeat_enable; +uniform bool foliage = false; +uniform bool bark = false; +uniform bool soil = false; +uniform bool paving = false; +varying vec3 world; +varying vec3 world_normal; +float hash(vec3 p) { p=fract(p*.1031); p+=dot(p,p.yzx+33.33); return fract((p.x+p.y)*p.z); } +float noise(vec3 p) { + vec3 i=floor(p),f=fract(p); f=f*f*(3.0-2.0*f); + return mix(mix(mix(hash(i),hash(i+vec3(1,0,0)),f.x),mix(hash(i+vec3(0,1,0)),hash(i+vec3(1,1,0)),f.x),f.y),mix(mix(hash(i+vec3(0,0,1)),hash(i+vec3(1,0,1)),f.x),mix(hash(i+vec3(0,1,1)),hash(i+vec3(1,1,1)),f.x),f.y),f.z); +} +void vertex() { + world=(MODEL_MATRIX*vec4(VERTEX,1.0)).xyz; + world_normal=normalize(mat3(MODEL_MATRIX)*NORMAL); + if(foliage) { + float wind=sin(TIME*.8+world.x*.55+world.z*.32)*sin(TIME*.37+world.z*.6); + VERTEX.x+=wind*.065*clamp(world.y*.3,.15,1.0); + } +} +void fragment() { + vec3 weights=pow(abs(world_normal),vec3(5.0)); weights/=max(dot(weights,vec3(1.0)),.0001); + vec3 p=world*.23; + vec3 stone=texture(stone_map,p.zy).rgb*weights.x+texture(stone_map,p.xz).rgb*weights.y+texture(stone_map,p.xy).rgb*weights.z; + float grain=noise(world*21.0); + float broad=noise(world*.8); + float relief=dot(stone,vec3(.333)); + ALBEDO=base_color.rgb*mix(vec3(.65),vec3(1.6),stone); + ROUGHNESS=.88; + if(paving) { ALBEDO=base_color.rgb*mix(vec3(.82),vec3(1.3),stone); } + if(soil) { + ALBEDO=base_color.rgb*mix(.82,1.12,broad)*mix(.78,1.2,relief); + ALBEDO=mix(ALBEDO,vec3(.12,.17,.075),smoothstep(.54,.8,broad)*.16); + } + if(bark) { + float ridges=noise(world*vec3(13,1.2,13)); + ALBEDO=base_color.rgb*mix(.45,1.2,ridges)*mix(.8,1.08,grain); + relief=ridges; + } + if(foliage) { + ALBEDO=base_color.rgb*mix(.75,1.2,broad); + ROUGHNESS=.79; + BACKLIGHT=ALBEDO*.32; + } + vec3 n=NORMAL,dx=dFdx(VERTEX),dy=dFdy(VERTEX); + vec3 rx=cross(dy,n),ry=cross(n,dx); float det=dot(dx,rx); + vec3 gradient=dFdx(relief)*rx+dFdy(relief)*ry; + if(!foliage) { NORMAL=normalize(abs(det)*n-sign(det)*gradient*(bark ? .025 : .016)); } +} diff --git a/scripts/presentation/sanctuary.gdshader.uid b/scripts/presentation/sanctuary.gdshader.uid new file mode 100644 index 0000000..66110e7 --- /dev/null +++ b/scripts/presentation/sanctuary.gdshader.uid @@ -0,0 +1 @@ +uid://b7mvtnimyd21v diff --git a/scripts/presentation/skeletal_figure.gd b/scripts/presentation/skeletal_figure.gd new file mode 100644 index 0000000..b18a491 --- /dev/null +++ b/scripts/presentation/skeletal_figure.gd @@ -0,0 +1,156 @@ +extends Node3D +## Imported, weighted character. The battle clock owns playback, including pause/2×. +var skeleton: Skeleton3D +var player: AnimationPlayer +var bounds: AABB +var clips: Dictionary = {} +var attack_cycle: Array[String] = ["attack_a", "attack_b"] +var current_clip: String = "" +var dead: bool = false +var _clock: float = 0.0 +var _walk_clock: float = 0.0 +var _event_left: float = 0.0 +var _last_hits: int = 0 +var _had_attack: bool = false +var _last_ability: float = 0.0 +var _last_hit: float = 0.0 +var _moving: bool = false +var _preview_time: float = 0.0 +var _ability_time: float = -1.0 +var _hit_time: float = -1.0 + +func setup(source: Node3D, box: AABB) -> void: + bounds = box + add_child(source) + for node: Node in source.find_children("*", "Skeleton3D", true, false): + skeleton = node as Skeleton3D + for node: Node in source.find_children("*", "AnimationPlayer", true, false): + player = node as AnimationPlayer + if player != null: + player.callback_mode_process = AnimationMixer.ANIMATION_CALLBACK_MODE_PROCESS_MANUAL + player.playback_default_blend_time = .12 + for key: String in player.get_animation_list(): + var short_name: String = key.get_slice("/",key.get_slice_count("/")-1) + clips[short_name] = key + +func get_aabb() -> AABB: + return bounds + +func clip_length(clip: String) -> float: + return player.get_animation(clips[clip]).length if clips.has(clip) else 0.0 + +func _sample(clip: String, at: float, delta: float = 0.0, blend: float = .12) -> void: + if player == null or not clips.has(clip) or not is_inside_tree(): + return + if current_clip != clip: + player.play(clips[clip], blend) + current_clip = clip + player.advance(delta) + player.seek(clampf(at,0,clip_length(clip)),true) + +func preview(clip: String, at: float) -> void: + _sample(clip, at, 0.0, 0.0) + +func pose(time: float, moving: bool, attack: float, ability: float, hit: float) -> void: + # Legacy preview entry point, retained for model galleries and callers. + var dt: float = clampf(time-_preview_time,0,.1) + _preview_time = time + if attack > 0: + _sample("attack_a",.90+(.28-attack),dt) + elif ability > 0: + _sample("ability",fmod(time,clip_length("ability")),dt) + elif hit > 0: + _sample("hit",.18-hit,dt) + else: + var clip: String = "walk" if moving else "idle" + _sample(clip,fmod(time,clip_length(clip)),dt) + +func update_combat(delta: float, distance: float, in_range: bool, progress: float, hits: int, ability: float, hit: float, living: bool) -> void: + if not living: + if not dead: + dead = true + _clock = 0.0 + _clock += delta + _sample("death",_clock,delta,.06) + return + _clock += delta + var moving: bool = delta > 0 and distance / delta > .04 + # Direct damage stays in AttackComponent. Pose reaches contact exactly on its event. + if in_range: + if hits > _last_hits: + _had_attack = true + _last_hits = hits + var recovering: bool = _had_attack and progress < .30 + var index: int = maxi(0,hits-1) if recovering else hits + var clip: String = attack_cycle[index % attack_cycle.size()] + var at: float = .90+.35*progress/.30 if recovering else .90*maxf(0,progress-(.30 if _had_attack else 0.0))/(.70 if _had_attack else 1.0) + _sample(clip,at,delta,.055) + _event_left = 0 + else: + _had_attack = false + _last_hits = hits + if ability > _last_ability + .05: + _event_left = clip_length("ability") + _clock = 0.0 + _sample("ability",0,delta) + elif hit > _last_hit + .05 and _event_left <= 0.0: + _event_left = clip_length("hit") + _clock = 0.0 + _sample("hit",0,delta,.045) + if _event_left > 0: + _event_left -= delta + _sample(current_clip,_clock,delta) + elif moving: + if not _moving: + _clock = 0.0 + # One stride travels 0.52 metres. Separation and slow effects affect cadence. + _walk_clock += distance / .52 * clip_length("walk") + if _clock < clip_length("start"): + _sample("start",_clock,delta) + else: + _sample("walk",fmod(_walk_clock,clip_length("walk")),delta) + else: + if _moving: + _clock = 0.0 + if current_clip in ["walk","start","stop"] and _clock < clip_length("stop"): + _sample("stop",_clock,delta) + else: + _sample("idle",fmod(_clock,clip_length("idle")),delta) + if ability > _last_ability + .05: + _ability_time = 0.0 + if hit > _last_hit + .05: + _hit_time = 0.0 + if _ability_time >= 0: + _ability_time += delta + if in_range: + _overlay("ability",_ability_time,.45,["Head","Forearm.L","Forearm.R"]) + if _ability_time >= clip_length("ability"): + _ability_time = -1.0 + if _hit_time >= 0: + _hit_time += delta + if in_range: + _overlay("hit",_hit_time,.65,["Spine","Head"]) + if _hit_time >= clip_length("hit"): + _hit_time = -1.0 + _last_ability = ability + _last_hit = hit + _moving = moving + +func _overlay(clip: String, at: float, weight: float, bones: Array) -> void: + # Only selected joints react while the primary swing keeps its contact time. + if not is_inside_tree() or not clips.has(clip): + return + var animation: Animation = player.get_animation(clips[clip]) + for track: int in range(animation.get_track_count()): + if animation.track_get_type(track) != Animation.TYPE_ROTATION_3D: + continue + var path: NodePath = animation.track_get_path(track) + if path.get_subname_count() == 0 or not str(path.get_subname(0)) in bones: + continue + var index: int = skeleton.find_bone(path.get_subname(0)) + if index < 0: + continue + var rest: Quaternion = skeleton.get_bone_rest(index).basis.get_rotation_quaternion() + var value: Quaternion = animation.rotation_track_interpolate(track,minf(at,animation.length)) + var offset: Quaternion = Quaternion.IDENTITY.slerp(rest.inverse()*value,weight) + skeleton.set_bone_pose_rotation(index,skeleton.get_bone_pose_rotation(index)*offset) diff --git a/scripts/presentation/skeletal_figure.gd.uid b/scripts/presentation/skeletal_figure.gd.uid new file mode 100644 index 0000000..0bf38ff --- /dev/null +++ b/scripts/presentation/skeletal_figure.gd.uid @@ -0,0 +1 @@ +uid://dr1npjwfierub diff --git a/scripts/presentation/soundscape.gd b/scripts/presentation/soundscape.gd new file mode 100644 index 0000000..69ad328 --- /dev/null +++ b/scripts/presentation/soundscape.gd @@ -0,0 +1,70 @@ +extends Node +## A bounded pool and wall-clock spacing keep 2x battles from flooding audio. + +const CLIPS: Array[String] = ["place", "error", "stone", "bolt", "mortar", "ember", "ability", "wave", "boss", "settle", "leak", "victory", "defeat"] +var viewed_team: int = 0 +var enabled: bool = true +var played: int = 0 +var _streams: Dictionary = {} +var _players: Array[AudioStreamPlayer] = [] +var _last: Dictionary = {} +var _last_combat: int = -1000 + +func _ready() -> void: + enabled = DisplayServer.get_name() != "headless" + for id: String in CLIPS: + _streams[id] = load("res://assets/audio/" + id + ".wav") + for index: int in range(12): + var player := AudioStreamPlayer.new() + add_child(player) + _players.append(player) + GameState.phase_changed.connect(_phase_changed) + +func play(id: String, lane: int = -1, combat: bool = false, pitch: float = 1.0) -> bool: + if not enabled or Preferences.muted or Preferences.volume <= 0.0 or not _streams.has(id): + return false + if lane >= 0 and lane != viewed_team: + return false + if combat and (GameState.paused or GameState.phase != GameState.Phase.COMBAT): + return false + var now: int = Time.get_ticks_msec() + if now - int(_last.get(id, -2000)) < (110 if combat else 80): + return false + if combat and now - _last_combat < 65: + return false + # Reserve two channels for wave/result/UI cues. + for index: int in range(10 if combat else 12): + var player: AudioStreamPlayer = _players[index] + if player.playing: + continue + player.stream = _streams[id] + player.volume_db = -13.0 if combat else -5.0 + player.pitch_scale = clampf(pitch, .85, 1.15) + player.play() + _last[id] = now + if combat: + _last_combat = now + played += 1 + return true + return false + +func stop_combat() -> void: + for player: AudioStreamPlayer in _players: + player.stop() + +func quit_game(code: int = 0) -> void: + enabled = false + stop_combat() + # Let the audio mixer release playback references before the tree is freed. + await get_tree().create_timer(.12).timeout + get_tree().quit(code) + +func _phase_changed(phase: int) -> void: + stop_combat() + match phase: + GameState.Phase.COMBAT: + play("boss" if GameState.wave in [5, 8] else "wave") + GameState.Phase.RESULTS: + play("settle") + GameState.Phase.GAME_OVER: + play("victory" if GameState.outcome == 0 else ("settle" if GameState.outcome == GameState.DRAW else "defeat")) diff --git a/scripts/presentation/soundscape.gd.uid b/scripts/presentation/soundscape.gd.uid new file mode 100644 index 0000000..c7cd286 --- /dev/null +++ b/scripts/presentation/soundscape.gd.uid @@ -0,0 +1 @@ +uid://wulmlp1k5xc7 diff --git a/scripts/presentation/stone_floor.gdshader b/scripts/presentation/stone_floor.gdshader new file mode 100644 index 0000000..a237148 --- /dev/null +++ b/scripts/presentation/stone_floor.gdshader @@ -0,0 +1,32 @@ +shader_type spatial; +render_mode diffuse_burley, specular_disabled; +uniform sampler2D limestone : source_color, filter_linear_mipmap_anisotropic, repeat_enable; + +uniform vec3 stone_color : source_color = vec3(.23, .24, .27); +uniform bool build_tile = false; +varying vec3 world_position; + +float grain(vec2 p) { + return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); +} + +void vertex() { + world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; +} + +void fragment() { + vec2 p = world_position.xz; + float fine = grain(floor(p * 38.0)); + float slabs = grain(floor(p / 2.0)); + vec2 cell = abs(fract(p / 2.0) - .5); + float seam = smoothstep(.478, .498, max(cell.x, cell.y)); + vec2 edge = min(UV, 1.0 - UV); + float rim = 1.0 - smoothstep(.008, .025, min(edge.x, edge.y)); + vec3 surface = texture(limestone, p * .26).rgb; + ALBEDO = stone_color * (.73 + surface * .6 + slabs * .08); + ALBEDO *= 1.0 - seam * (build_tile ? .06 : .35); + if (build_tile) { + ALBEDO += vec3(.045, .055, .040) * rim; + } + ROUGHNESS = .93; +} diff --git a/scripts/presentation/stone_floor.gdshader.uid b/scripts/presentation/stone_floor.gdshader.uid new file mode 100644 index 0000000..bb76d17 --- /dev/null +++ b/scripts/presentation/stone_floor.gdshader.uid @@ -0,0 +1 @@ +uid://by5yiy0ka02m7 diff --git a/scripts/presentation/worker_figure.gd b/scripts/presentation/worker_figure.gd new file mode 100644 index 0000000..ca26ec0 --- /dev/null +++ b/scripts/presentation/worker_figure.gd @@ -0,0 +1,47 @@ +extends "res://scripts/presentation/skeletal_figure.gd" +## Funkenleser work loop: tool contact, gather, deposit into the reservoir, return. + +const WORK_STEPS: Array = ["strike", "pickup", "deposit", "return"] +const WORK_GAP: float = 0.7 +const STRIKE_CONTACT: float = 0.62 +var _work_clock: float = 0.0 +var _strike_contact_pending: bool = false + +func cycle_length() -> float: + var total: float = WORK_GAP + for clip: String in WORK_STEPS: + total += clip_length(clip) + return total + +func update_work(delta: float, phase: float = 0.0) -> void: + if player == null or not is_inside_tree(): + return + var cycle: float = cycle_length() + var before: float = _work_clock + phase + _work_clock += maxf(delta, 0.0) + var after: float = _work_clock + phase + var contact: float = STRIKE_CONTACT * clip_length("strike") + # Count an actual crossing, including across the loop boundary. A time window + # can fire twice when consumed every frame, or fire after a phase-offset spawn. + if delta > 0.0 and floorf((after - contact) / cycle) > floorf((before - contact) / cycle): + _strike_contact_pending = true + var t: float = fposmod(after, cycle) + var cursor: float = 0.0 + for clip: String in WORK_STEPS: + var length: float = clip_length(clip) + if t < cursor + length: + var local: float = t - cursor + _sample(clip, local, delta, .08) + return + cursor += length + _sample("idle", t - cursor, delta, .08) + +func consume_strike_contact() -> bool: + if _strike_contact_pending: + _strike_contact_pending = false + return true + return false + +func preview(clip: String, at: float) -> void: + _strike_contact_pending = false + super.preview(clip, at) diff --git a/scripts/presentation/worker_figure.gd.uid b/scripts/presentation/worker_figure.gd.uid new file mode 100644 index 0000000..47f61f6 --- /dev/null +++ b/scripts/presentation/worker_figure.gd.uid @@ -0,0 +1 @@ +uid://ceplg0e3rur0f diff --git a/scripts/qa/expedition_test.gd b/scripts/qa/expedition_test.gd new file mode 100644 index 0000000..ff9ed21 --- /dev/null +++ b/scripts/qa/expedition_test.gd @@ -0,0 +1,168 @@ +extends Node +## Acceptance against production rules, also runnable from the exported program. +const AI = preload("res://scripts/ai/simple_ai.gd") +const Unit = preload("res://scripts/combat/unit.gd") +var checks: int = 0 +var failures: Array[String] = [] +var matches: Array[Dictionary] = [] +var main: Node3D + +func check(value: bool, message: String) -> void: + checks += 1 + if not value: + failures.append(message) + printerr("EXPEDITION_FAIL: ", message) + +func capture(label: String) -> void: + if DisplayServer.get_name() == "headless": + return + await get_tree().process_frame + await get_tree().create_timer(.25).timeout + await RenderingServer.frame_post_draw + DirAccess.make_dir_recursive_absolute("user://phase8-captures") + check(get_viewport().get_texture().get_image().save_png("user://phase8-captures/"+label+".png") == OK, "Capture " + label) + +func run(scene: Node3D) -> void: + main = scene + WaveManager.set_physics_process(false) + Soundscape.enabled = false + main.battle.render_enabled = DisplayServer.get_name() != "headless" + GameState.reset_match() + GameState.factions = ["glutpakt", "glutpakt"] + GameState.timed_build = true + main.hud._mode_picker.item_selected.emit(1) + check(DataCatalog.wave_count() == 8 and DataCatalog.get_wave(9).is_empty(), "Short match remains eight waves") + check(DataCatalog.get_wave(8).groups.has("e08"), "Short finale remains Riegelkoloss") + main.hud._mode_picker.item_selected.emit(0) + check(DataCatalog.wave_count() == 20 and "Zwanzig" in main.hud._overlay_title.text, "Menu selects the twenty-wave expedition") + check(DataCatalog.get_wave(0).is_empty() and DataCatalog.get_wave(21).is_empty(), "Wave bounds reject out-of-range requests") + for number: int in range(1,21): + var wave: Dictionary = DataCatalog.get_wave(number) + check(wave.count == DataCatalog.get_attackers(number).size() and not wave.hint.is_empty(), "Wave %d has composition and counter hint" % number) + if number % 5 == 0: + check(wave.groups.has("e%02d" % (6+number/5)), "Boss appears at wave %d" % number) + if number > 1: + var previous: Dictionary = DataCatalog.get_wave(number-1) + check(wave.hp_factor > previous.hp_factor and wave.damage_factor > previous.damage_factor, "Wave %d scales upward" % number) + for id: String in ["e05","e06","e09","e10"]: + var model: Node3D = AssetLibrary.instantiate_fighter(id) + check(model != null and model.has_method("pose"), id + " has its own articulated model") + if model != null: + check(AssetLibrary._models[id].triangles > 15000, id + " has modeled detail") + var baked: ArrayMesh = AssetLibrary.bake_mesh(model) + check(baked.get_aabb().size.y > 1.5, id + " has correct world scale") + model.pose(.2,true,.14,.3,0) + model.free() + _test_abilities() + await capture("menu") + await _play("Standard gegen Standard",GameState.AI_STANDARD,GameState.AI_STANDARD,GameState.DRAW,true) + await _play("Standard gegen Lernmodus",GameState.AI_STANDARD,GameState.AI_LEARNING,0) + await _play("Leeres Baufeld gegen Standard",-1,GameState.AI_STANDARD,1) + main.hud._mode_picker.item_selected.emit(1) + main.hud._overlay_action.pressed.emit() + check(GameState.wave == 1 and DataCatalog.wave_count() == 8 and GameState.core_hp == [3000,3000], "Restart after expedition can select a fresh short match") + check(EconomyManager.get_team(0).gold == 220 and EconomyManager.get_team(0).roster.is_empty(), "Restart clears all expedition purchases") + check(not GameState.select_mode(GameState.MODE_EXPEDITION) and DataCatalog.wave_count() == 8, "Match length cannot change during an active match") + var file := FileAccess.open("user://phase8-verification.json",FileAccess.WRITE) + file.store_string(JSON.stringify({"checks":checks,"failures":failures,"matches":matches,"engine":Engine.get_version_info().string},"\t")) + file.close() + print("EXPEDITION_PASS: %d checks; %d failures; report %s" % [checks,failures.size(),ProjectSettings.globalize_path("user://phase8-verification.json")]) + await Soundscape.quit_game(0 if failures.is_empty() else 1) + +func _play(title: String, player_level: int, rival_level: int, expected: int, pictures: bool = false) -> void: + GameState.reset_match() + GameState.select_mode(GameState.MODE_EXPEDITION) + GameState.ai_level = rival_level + WaveManager.start_match() + var ai := AI.new() + var waves: Array[Dictionary] = [] + for number: int in range(1,21): + check(GameState.wave == number and GameState.phase == GameState.Phase.BUILD,title + " build %d" % number) + if player_level >= 0: + ai.plan(0,number,WaveManager.rival_snapshot(),GameState.last_reports[0],player_level) + var plan: Dictionary = EconomyManager.get_team(0) + check(plan.gold >= 0 and EconomyManager.reserved_sparks(0) <= mini(plan.sparks,EconomyManager.send_budget(number)),title + " paid purchases and sends %d" % number) + if number == 20: + var result: Dictionary = EconomyManager.apply_command(0,{"type":"worker"}) + check(not result.ok and "letzten Welle" in result.message,"No worker investment in the final wave") + WaveManager.ready_for_battle() + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: + break + WaveManager.advance(1.0/60.0) + if pictures and step == 280 and number in [9,15,20]: + await capture("wave-%02d" % number) + check(GameState.phase in [GameState.Phase.RESULTS,GameState.Phase.GAME_OVER],title + " settled %d" % number) + waves.append({"wave":number,"seconds":main.battle.elapsed,"core_hp":GameState.core_hp.duplicate(),"leaks":main.battle.leaks.duplicate(),"gold":plan.gold,"workers":plan.workers,"pending_workers":plan.pending_workers,"sends":plan.send_queue,"formation":_roster(plan.roster)}) + if GameState.phase == GameState.Phase.GAME_OVER: + break + WaveManager.ready_for_battle() + check(GameState.outcome == expected,title + " expected outcome") + if player_level == rival_level: + check(GameState.wave == 20 and GameState.core_hp[0] > 0,"Symmetric match reaches and resolves the real final boss") + if pictures: + await capture("result") + matches.append({"title":title,"outcome":GameState.outcome,"waves":waves}) + print("EXPEDITION_MATCH: ",title,"; wave ",GameState.wave,"; cores ",GameState.core_hp,"; outcome ",GameState.outcome) + +func _roster(entries: Array) -> Array: + var result: Array = [] + for entry: Dictionary in entries: + result.append({"id":entry.type_id,"uid":entry.uid,"cell":[entry.cell.x,entry.cell.y],"invested":entry.invested}) + return result + +func _unit(id: String, uid: int, lane: int = 0, attacker: bool = true) -> Node3D: + var unit := Unit.new() + add_child(unit) + var data: Dictionary = DataCatalog.ENEMIES[id].duplicate(true) if attacker else DataCatalog.get_unit(id) + unit.setup(data,uid,lane,attacker,Vector2i(-1,-1),0,false) + return unit + +func _test_abilities() -> void: + var healer := _unit("e06",1) + var ally := _unit("e05",2) + var wrong_lane := _unit("e05",3,1) + ally.hp = 100 + wrong_lane.hp = 10 + healer.combat_time = 6 + healer.data.hp_factor = 2.0 + healer.ability_component.step(healer,[healer,ally,wrong_lane],0) + check(is_equal_approx(ally.hp,160) and is_equal_approx(wrong_lane.hp,10),"Knotenrufer heals 30 times wave factor in its own lane") + healer.ability_component.step(healer,[healer,ally],0) + check(is_equal_approx(ally.hp,160),"Healing observes its six-second cooldown") + for unit: Node3D in [healer,ally,wrong_lane]: unit.free() + var judge := _unit("e09",1) + var victims: Array = [] + for i: int in range(5): + var unit := _unit("g03",10+i,0,false) + unit.position.x = .2*i + victims.append(unit) + judge.combat_time = 6 + judge.ability_component.step(judge,[judge]+victims,0) + for i: int in range(5): + check(victims[i].effects.has("dissonance") == (i<3),"Maskenrichter slow target limit %d" % i) + victims[i].advance_status(3.0) + check(not victims[i].effects.has("dissonance"),"Maskenrichter slow expires %d" % i) + victims[i].free() + judge.free() + for id: String in ["e05","e10"]: + var source := _unit(id,1) + var primary := _unit("g03",10,0,false) + var extras: Array = [] + for i: int in range(6): + var unit := _unit("g03",20+i,0,false) + unit.data.ability = "" + unit.data.armor_type = source.data.attack_type + unit.position.x = .1*(i+1) + extras.append(unit) + var hp: float = extras[0].hp + source.ability_component.on_hit(source,primary,[source,primary]+extras,3) + check(is_equal_approx(extras[0].hp,hp),id + " no splash before fourth hit") + source.ability_component.on_hit(source,primary,[source,primary]+extras,4) + for i: int in range(6): + var loss: float = source.data.damage*(.40 if id=="e05" else .60)*1.3 if i<(2 if id=="e05" else 4) else 0.0 + check(is_equal_approx(extras[i].hp,hp-loss),id+" exact fourth-hit splash target %d"%i) + extras[i].free() + check(primary.hp == primary.max_hp,id+" splash excludes primary") + primary.free() + source.free() diff --git a/scripts/qa/expedition_test.gd.uid b/scripts/qa/expedition_test.gd.uid new file mode 100644 index 0000000..6a7a4af --- /dev/null +++ b/scripts/qa/expedition_test.gd.uid @@ -0,0 +1 @@ +uid://b2jxf5ge6j6q6 diff --git a/scripts/qa/export_smoke.gd b/scripts/qa/export_smoke.gd new file mode 100644 index 0000000..6a2cd2a --- /dev/null +++ b/scripts/qa/export_smoke.gd @@ -0,0 +1,281 @@ +extends Node +## Opt-in QA entry point. Runs inside the actual release PCK with ordinary budgets. +const AI = preload("res://scripts/ai/simple_ai.gd") +const RELEASE_MODELS: Dictionary = { + "w04": ["res://assets/phase11_manifest.json", "res://assets/characters/ringborke.glb", 27], + "worker": ["res://assets/phase12_manifest.json", "res://assets/characters/arbeiter.glb", 27], + "g04": ["res://assets/phase15_manifest.json", "res://assets/characters/basaltbastion.glb", 17], + "w10": ["res://assets/phase16_manifest.json", "res://assets/characters/quellgeflecht.glb", 17], + "g05": ["res://assets/phase18_manifest.json", "res://assets/characters/funkenlanze.glb", 26], + "g06": ["res://assets/phase19_manifest.json", "res://assets/characters/glasballiste.glb", 20], +} +const FIGHTER_CLIPS: Array[String] = ["idle", "start", "walk", "stop", "attack_a", "attack_b", "hit", "ability", "death"] +const WORKER_CLIPS: Array[String] = ["idle", "start", "walk", "stop", "strike", "pickup", "deposit", "return", "hit", "death"] +var checks: int = 0 +var failures: Array[String] = [] + +func check(value: bool, message: String) -> void: + checks += 1 + if not value: + failures.append(message) + printerr("SMOKE_FAIL: ", message) + +func triangles(mesh: Mesh) -> int: + var total: int = 0 + for index: int in range(mesh.get_surface_count()): + var arrays: Array = mesh.surface_get_arrays(index) + var indices: PackedInt32Array = arrays[Mesh.ARRAY_INDEX] + var vertices: PackedVector3Array = arrays[Mesh.ARRAY_VERTEX] + total += (indices.size() if not indices.is_empty() else vertices.size()) / 3 + return total + +func key(code: Key) -> void: + var event := InputEventKey.new() + event.keycode = code + event.pressed = true + get_viewport().push_input(event, true) + event = event.duplicate() + event.pressed = false + get_viewport().push_input(event, true) + +func capture(label: String) -> void: + if DisplayServer.get_name() == "headless": + return + await get_tree().process_frame + await get_tree().create_timer(.22).timeout + await RenderingServer.frame_post_draw + var directory: String = "user://phase8-smoke" + DirAccess.make_dir_recursive_absolute(directory) + check(get_viewport().get_texture().get_image().save_png(directory + "/" + label + ".png") == OK, "Capture " + label) + +func check_release_assets() -> void: + # Branching on has_method("update_combat") also lets the rigid fallback pass. + # Require the release's exact manifest selection and the instantiated skin/clips. + for path: String in ["res://assets/phase3_manifest.json", "res://assets/phase4_manifest.json", "res://assets/phase11_manifest.json", "res://assets/phase12_manifest.json", "res://assets/phase15_manifest.json", "res://assets/phase16_manifest.json", "res://assets/phase18_manifest.json", "res://assets/phase19_manifest.json", "res://assets/menu_stage_manifest.json", "res://assets/audio/manifest.json", "res://assets/icons/manifest.json"]: + check(FileAccess.file_exists(path), "Packaged runtime manifest " + path) + if FileAccess.file_exists(path): + check(JSON.parse_string(FileAccess.get_file_as_string(path)) is Dictionary, "Valid runtime manifest " + path) + # Phase 20A menu: emblems, control icons, fonts and the diorama must ship in the package. + for path: String in ["res://assets/ui/emblems/saumwacht.svg", "res://assets/ui/emblems/glutpakt.svg", "res://assets/ui/emblems/wurzelbund.svg", + "res://assets/ui/controls/toggle_on.svg", "res://assets/ui/controls/toggle_off.svg", "res://assets/ui/controls/choice_on.svg", "res://assets/ui/controls/choice_off.svg"]: + check(load(path) is Texture2D, "Packaged menu graphic " + path.get_file()) + for path: String in ["res://assets/fonts/Cinzel-VF.ttf", "res://assets/fonts/Alegreya-VF.ttf", "res://assets/fonts/Alegreya-Italic-VF.ttf"]: + check(load(path) is Font, "Packaged menu font " + path.get_file()) + check(load("res://assets/environment/menu-stage.glb") is PackedScene, "Packaged menu diorama") + for id: String in RELEASE_MODELS: + var expected: Array = RELEASE_MODELS[id] + var record: Dictionary = AssetLibrary._models.get(id, {}) + var selected: bool = record.get("skeletal", false) and record.get("resource_path", "") == expected[1] + check(selected, id + " selects the current skeletal release asset") + check(ResourceLoader.exists(expected[1]), id + " skeletal resource is packaged") + if not selected or not ResourceLoader.exists(expected[1]): + continue + var a: Node3D = AssetLibrary.instantiate_fighter(id) + var b: Node3D = AssetLibrary.instantiate_fighter(id) + check(a is AssetLibrary.SkeletalFigure and b is AssetLibrary.SkeletalFigure, id + " instantiates the skeletal runtime") + if not (a is AssetLibrary.SkeletalFigure and b is AssetLibrary.SkeletalFigure): + if a != null: + a.free() + if b != null: + b.free() + continue + add_child(a) + add_child(b) + check(a.skeleton != null and a.player != null, id + " imports skeleton and animation player") + if a.skeleton == null or a.player == null or b.skeleton == null or b.player == null: + a.free() + b.free() + continue + check(a.skeleton.get_bone_count() == expected[2], id + " has the current authored bone count") + check(a.skeleton != b.skeleton and a.player != b.player, id + " skeleton and playback are per instance") + var weighted_meshes: int = 0 + for mesh: MeshInstance3D in a.find_children("*", "MeshInstance3D", true, false): + if mesh.skin != null and mesh.get_node_or_null(mesh.skeleton) == a.skeleton: + weighted_meshes += 1 + check(weighted_meshes > 0, id + " mesh binds to the imported skeleton") + var required: Array[String] = WORKER_CLIPS if id == "worker" else FIGHTER_CLIPS + for clip: String in required: + check(a.clips.has(clip), id + " imports authored clip " + clip) + if a.clips.has(clip): + var animation: Animation = a.player.get_animation(a.clips[clip]) + check(animation.length > .1 and animation.get_track_count() > 0, id + " has playable tracks for " + clip) + if a.clips.has("walk"): + var own_rest: Array[Transform3D] = [] + var other_rest: Array[Transform3D] = [] + for bone: int in range(a.skeleton.get_bone_count()): + own_rest.append(a.skeleton.get_bone_pose(bone)) + other_rest.append(b.skeleton.get_bone_pose(bone)) + a.preview("walk", a.clip_length("walk") * .25) + var changed: bool = false + var independent: bool = true + for bone: int in range(a.skeleton.get_bone_count()): + changed = changed or not a.skeleton.get_bone_pose(bone).is_equal_approx(own_rest[bone]) + independent = independent and b.skeleton.get_bone_pose(bone).is_equal_approx(other_rest[bone]) + check(changed, id + " clip drives actual bone poses") + check(independent, id + " playback leaves the other instance unchanged") + if id == "worker": + check(a is AssetLibrary.WorkerFigure and a.has_method("update_work"), "Worker uses the current work-cycle runtime") + if a is AssetLibrary.WorkerFigure and required.all(func(clip: String) -> bool: return a.clips.has(clip)): + var seen: Dictionary = {} + var contacts: int = 0 + for step: int in range(ceili(a.cycle_length() * 60.0)): + a.update_work(1.0 / 60.0) + seen[a.current_clip] = true + if a.consume_strike_contact(): + contacts += 1 + for clip: String in ["strike", "pickup", "deposit", "return", "idle"]: + check(seen.has(clip), "Worker work cycle plays " + clip) + check(contacts == 1, "Worker emits one tool contact per complete work cycle") + a.free() + b.free() + +func run(main: Node3D) -> void: + GameState.reset_match() + GameState.factions = ["glutpakt", "glutpakt"] + GameState.timed_build = true + GameState.select_mode(GameState.MODE_SHORT) + WaveManager.set_physics_process(false) + Soundscape.enabled = false + await get_tree().process_frame + check_release_assets() + if not failures.is_empty(): + printerr("EXPORT_SMOKE_FAIL: %d release asset failures" % failures.size()) + await Soundscape.quit_game(1) + return + for id: String in DataCatalog.UNITS: + var a: Node3D = AssetLibrary.instantiate_fighter(id) + var b: Node3D = AssetLibrary.instantiate_fighter(id) + var static_model := AssetLibrary.instantiate_model(id) as MeshInstance3D + check(a != null and a.has_method("pose"), id + " has articulated model") + if a != null and a.has_method("pose"): + var mesh: ArrayMesh = AssetLibrary.bake_mesh(a) + check(triangles(mesh) == triangles(static_model.mesh), id + " rig retains every triangle") + # Skeletal remakes are judged by form and motion, not a raw poly floor. + var poly_floor: int = 14000 if a.has_method("update_combat") else 20000 + check(triangles(mesh) > poly_floor, id + " has high-detail geometry") + check(mesh.get_aabb().position.distance_to(static_model.get_aabb().position) < .001 and mesh.get_aabb().end.distance_to(static_model.get_aabb().end) < .001, id + " neutral pose retains original bounds") + if a.has_method("update_combat"): + check(a.skeleton != b.skeleton, id + " skeleton is per instance") + check(a.clips.size() >= 9, id + " contains authored animation clips") + a.free() + b.free() + static_model.free() + continue + check(a.parts.has("LegL") and a.parts.has("LegR"), id + " has two separate leg joints") + var other_leg: Transform3D = b.parts.LegL.transform + a.pose(.25, true, .14, .4, .12) + check(absf(a.parts.LegL.rotation.x) > .005 and a.parts.LegL.rotation.x * a.parts.LegR.rotation.x < 0, id + " legs step in opposition") + check(b.parts.LegL.transform == other_leg, id + " animation does not move another unit") + check(a.parts.LegL.mesh == b.parts.LegL.mesh, id + " immutable joint geometry is shared") + check(a.parts.LegL.material_overlay != b.parts.LegL.material_overlay, id + " hit tint is per instance") + a.free() + b.free() + static_model.free() + for id: String in ["e01","e02","e03","e04","e07","e08"]: + var figure: Node3D = AssetLibrary.instantiate_fighter(id) + var still: Node3D = AssetLibrary.instantiate_model(id) + var baked: ArrayMesh = AssetLibrary.bake_mesh(figure) + check(figure.has_method("pose") and triangles(baked) > 10000, id + " articulated high-detail enemy") + check(triangles(baked) == triangles(still.mesh), id + " enemy rig retains every triangle") + check(baked.get_aabb().end.distance_to(still.get_aabb().end) < .001, id + " enemy neutral bounds") + figure.free() + still.free() + for id: String in Soundscape.CLIPS: + var stream := load("res://assets/audio/" + id + ".wav") as AudioStreamWAV + check(stream != null and stream.get_length() > .1, "Packaged audio " + id) + for id: String in DataCatalog.UNITS.keys() + DataCatalog.SENDS.keys() + ["worker", "res_gold", "res_sparks", "res_income", "res_core"]: + check(AssetLibrary.icon(id) != null, "Packaged icon " + id) + check(AssetLibrary.missing.is_empty(), "No missing models") + await capture("menu") + main.hud._overlay_action.pressed.emit() + main.hud._starter_button.pressed.emit() + check(GameState.phase == GameState.Phase.BUILD and EconomyManager.get_team(0).gold == 40, "Menu and paid starter work in package") + main.hud._ready_button.grab_focus() + key(KEY_V) + check(main.hud.model_inspector.visible and GameState.paused, "Model inspector pauses the match") + var inspect_remaining: float = WaveManager.remaining + WaveManager.advance(2) + key(KEY_SPACE) + check(main.hud.model_inspector.visible and WaveManager.remaining == inspect_remaining and GameState.phase == GameState.Phase.BUILD, "Inspector blocks ready shortcut and simulation") + main.hud.model_inspector._selector.item_selected.emit(3) + check(main.hud.model_inspector.model_id == "g04", "Inspector switches to selected upgrade") + main.hud.model_inspector._rotate_button.button_pressed = false + await capture("model-g04") + main.hud.model_inspector._select_model("g10") + await capture("model-g10") + main.hud.model_inspector._select_model("w10") + await capture("model-w10") + main.hud.model_inspector._select_model("worker") + await capture("model-worker") + key(KEY_ESCAPE) + check(not main.hud.model_inspector.visible and not GameState.paused and main.hud._ready_button.has_focus(), "Inspector restores running state and focus") + key(KEY_P) + key(KEY_V) + key(KEY_V) + check(GameState.paused, "Inspector preserves a pre-existing pause") + key(KEY_P) + key(KEY_F1) + check(main.hud.settings_panel.visible and GameState.paused, "Options pause the match") + var remaining: float = WaveManager.remaining + WaveManager.advance(2) + key(KEY_SPACE) + check(WaveManager.remaining == remaining and GameState.phase == GameState.Phase.BUILD, "Options block simulation and ready shortcut") + await capture("options") + key(KEY_ESCAPE) + check(not main.hud.settings_panel.visible and not GameState.paused, "Closing options restores running state") + key(KEY_P) + key(KEY_F1) + key(KEY_ESCAPE) + check(GameState.paused, "Options preserve a pre-existing pause") + key(KEY_P) + var basis: Basis = main.camera.basis + key(KEY_E) + check(main.camera.basis != basis, "Orbit key rotates camera") + key(KEY_R) + check(main.camera.basis.is_equal_approx(basis), "Reset restores default angle") + # Round trip in an isolated config file; restore the user's actual settings. + var path: String = Preferences.storage_path + var volume: float = Preferences.volume + var muted: bool = Preferences.muted + Preferences.storage_path = "user://phase8-smoke-preferences.cfg" + Preferences.volume = .37 + Preferences.muted = true + check(Preferences.save_settings() == OK, "Settings save") + Preferences.volume = .9 + Preferences.muted = false + Preferences.read_settings() + check(is_equal_approx(Preferences.volume, .37) and Preferences.muted, "Settings survive reload") + DirAccess.remove_absolute(Preferences.storage_path) + Preferences.storage_path = path + Preferences.volume = volume + Preferences.muted = muted + Preferences.apply() + await capture("build") + key(KEY_SPACE) + check(GameState.phase == GameState.Phase.COMBAT, "Ready starts combat") + for step: int in range(200): + WaveManager.advance(1.0/60.0) + await capture("combat") + # One full acceptance match, using normal production rules and resources. + GameState.ai_level = GameState.AI_LEARNING + WaveManager.start_match() + var player := AI.new() + for number: int in range(1, 9): + check(GameState.wave == number and GameState.phase == GameState.Phase.BUILD, "Wave %d build boundary" % number) + player.plan(0, number, WaveManager.rival_snapshot(), GameState.last_reports[0], GameState.AI_STANDARD) + WaveManager.ready_for_battle() + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: + break + WaveManager.advance(1.0/60.0) + if number == 8 and step == 330: + await capture("boss") + check(GameState.phase in [GameState.Phase.RESULTS, GameState.Phase.GAME_OVER], "Wave %d settles" % number) + if GameState.phase == GameState.Phase.GAME_OVER: + break + WaveManager.ready_for_battle() + check(GameState.wave == 8 and GameState.outcome == 0, "Actual eight-wave package match is winnable") + await capture("victory") + print("%s: %d checks; %d failures; engine %s; cores %s" % ["EXPORT_SMOKE_PASS" if failures.is_empty() else "EXPORT_SMOKE_FAIL", checks, failures.size(), Engine.get_version_info().string, str(GameState.core_hp)]) + print("SMOKE_CAPTURES: ", ProjectSettings.globalize_path("user://phase8-smoke")) + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/scripts/qa/export_smoke.gd.uid b/scripts/qa/export_smoke.gd.uid new file mode 100644 index 0000000..5dfcdc3 --- /dev/null +++ b/scripts/qa/export_smoke.gd.uid @@ -0,0 +1 @@ +uid://buqoncacud78g diff --git a/scripts/qa/faction_test.gd b/scripts/qa/faction_test.gd new file mode 100644 index 0000000..a70d966 --- /dev/null +++ b/scripts/qa/faction_test.gd @@ -0,0 +1,317 @@ +extends Node +## Phase 9 acceptance: ordinary paid commands, real input, both factions and modes. +const Unit = preload("res://scripts/combat/unit.gd") +const AI = preload("res://scripts/ai/simple_ai.gd") +var checks: int = 0 +var failures: Array[String] = [] +var matches: Array = [] +var fixtures: Array[Node] = [] +var main: Node3D +var pictures: bool = false + +func check(value: bool, label: String) -> void: + checks += 1 + if not value: + failures.append(label) + printerr("FACTION_FAIL: ", label) + +func run(scene: Node3D) -> void: + main = scene + pictures = DisplayServer.get_name() != "headless" + WaveManager.set_physics_process(false) + check(main.world.has_node("VerdantRift/LivingRiver"),"New landscape and animated river instantiated") + for map_path: String in ["oak-albedo-4k", "oak-height-4k"]: + var texture: Texture2D = load("res://assets/materials/phase10/"+map_path+".png") + check(texture != null and texture.get_size() == Vector2(4096,4096),"Native 4K map included: "+map_path) + Soundscape.enabled = false + main.battle.render_enabled = pictures + _test_abilities() + for id: String in DataCatalog.UNITS: + if not id.begins_with("w"): + continue + var model: Node3D = AssetLibrary.instantiate_fighter(id) + check(model != null and model.has_method("pose"), id+" articulated model") + # Skeletal remakes are judged by form and motion; rigid HD models keep the 20k floor. + var poly_min: int = 14000 if model.has_method("update_combat") else 20000 + check(AssetLibrary._models[id].triangles > poly_min and AssetLibrary._models[id].triangles <= 180000,id+" authored geometry within budget") + if model.has_method("update_combat"): + check(model.skeleton.find_bone("Thigh.L") >= 0 and model.skeleton.find_bone("Thigh.R") >= 0,id+" weighted leg bones") + else: + check(model.parts.has("LegL") and model.parts.has("LegR"),id+" independent roots") + model.pose(.4,true,.2,.2,0) + model.free() + await _test_interface() + if "--ui-only" not in OS.get_cmdline_user_args(): + await _play("Wurzelbund gegen Glutpakt", "wurzelbund", "glutpakt", GameState.MODE_EXPEDITION, true) + await _play("Glutpakt gegen Wurzelbund", "glutpakt", "wurzelbund", GameState.MODE_EXPEDITION) + await _play("Wurzelbund Spiegel", "wurzelbund", "wurzelbund", GameState.MODE_EXPEDITION) + await _play("Wurzelbund Kurzpartie", "wurzelbund", "wurzelbund", GameState.MODE_SHORT) + var path: String = "user://phase10-verification.json" + var file := FileAccess.open(path, FileAccess.WRITE) + file.store_string(JSON.stringify({"checks":checks,"failures":failures,"matches":matches,"renderer":RenderingServer.get_current_rendering_method(),"engine":Engine.get_version_info().string},"\t")) + file.close() + print("FACTION_PASS: %d checks; %d failures; %s" % [checks,failures.size(),ProjectSettings.globalize_path(path)]) + await Soundscape.quit_game(0 if failures.is_empty() else 1) + +func fixture(id: String, uid: int, team: int = 0, attacker: bool = false) -> CombatUnit: + var unit := Unit.new() + var data: Dictionary = DataCatalog.get_unit(id) if DataCatalog.UNITS.has(id) else DataCatalog.ENEMIES[id].duplicate(true) + unit.setup(data,uid,team,attacker,Vector2i.ZERO,0,false) + fixtures.append(unit) + return unit + +func _test_abilities() -> void: + for id: String in ["w03","w04"]: + var tank := fixture(id,1) + tank.combat_time = 5 + tank.ability_component.step(tank,[tank],0) + check(tank.ability_component.ready_time == 5,id+" does not spend heal on full HP") + tank.hp -= 150 + var before: float = tank.hp + tank.ability_component.step(tank,[tank],0) + check(is_equal_approx(tank.hp-before,100 if id == "w04" else 35),id+" self heal") + check(tank.ability_component.ready_time == 10,id+" five-second cooldown") + tank.ability_component.step(tank,[tank],0) + check(is_equal_approx(tank.hp-before,100 if id == "w04" else 35),id+" cannot heal twice in same instant") + for id: String in ["w09","w10"]: + var healer := fixture(id,10) + var near := fixture("w03",11) + var urgent := fixture("w03",12) + var third := fixture("w03",13) + var far := fixture("w03",14) + var dead := fixture("w03",15) + var rival := fixture("w03",16,1) + var foe := fixture("e02",17,0,true) + var army: Array = [healer,near,urgent,third,far,dead,rival,foe] + for ally in army: + ally.hp = ally.max_hp*.5 + healer.hp = healer.max_hp + near.position.x = .5 + urgent.position.x = 3.5 + urgent.hp = 1 + third.position.x = 2 + far.position.x = 5 + dead.alive = false + healer.combat_time = 4 + var before: float = near.hp + healer.ability_component.step(healer,army,0) + check(urgent.hp == (81 if id == "w10" else 66),id+" prioritizes lowest HP ratio") + check(near.hp == before+(80 if id == "w10" else 0),id+" target limit") + check(far.hp == far.max_hp*.5 and rival.hp == rival.max_hp*.5 and foe.hp == foe.max_hp*.5 and not dead.alive,id+" respects range, lane, allegiance and death") + check(healer.ability_component.ready_time == 8,id+" four-second cooldown") + healer.combat_time = 8 + urgent.apply_effect("rift_wound","healing_reduction",.30,4) + var hp: float = urgent.hp + healer.ability_component.step(healer,army,0) + check(is_equal_approx(urgent.hp-hp,(80 if id == "w10" else 65)*.70),id+" healing reduction applies") + for id: String in ["w01","w02"]: + var root := fixture(id,20) + var victim := fixture("e08",21,0,true) + root.ability_component.on_hit(root,victim,[root,victim],2) + check(victim.effects.is_empty(),id+" no early proc") + root.ability_component.on_hit(root,victim,[root,victim],3) + check(is_equal_approx(victim.movement_factor(),.85 if id == "w02" else .90),id+" boss movement slow is halved") + check(is_equal_approx(victim.attack_speed_factor(),.95 if id == "w02" else 1.0),id+" attack slow") + victim.advance_status(3) + check(victim.effects.is_empty(),id+" slow expires") + for id: String in ["w05","w06"]: + var archer := fixture(id,30) + var victim := fixture("e08",31,0,true) + victim.shield = 0 + archer.ability_component.on_hit(archer,victim,[archer,victim],3) + check(victim.dots.is_empty(),id+" waits until fourth hit") + archer.ability_component.on_hit(archer,victim,[archer,victim],4) + victim.apply_dot("burn",4,3,0) + check(victim.dots.has("burn") and victim.dots.has("seed_burn"),id+" independent burn families") + victim.dots.erase("burn") + var hp: float = victim.hp + for i in 4: + victim.advance_status(1) + check(is_equal_approx(hp-victim.hp,(10 if id == "w06" else 3)*4*1.30),id+" four scaled damage ticks") + check(victim.dots.is_empty(),id+" DOT expires") + for id: String in ["w07","w08"]: + var spore := fixture(id,40) + var primary := fixture("e02",41,0,true) + var army: Array = [spore,primary] + var targets: Array = [] + for i in 6: + var victim := fixture("e02",42+i,0,true) + victim.position.x = .1*(i+1) + targets.append(victim) + army.append(victim) + spore.apply_effect("warmth","damage",.3,4) + spore.ability_component.on_hit(spore,primary,army,3) + var maximum: int = 4 if id == "w08" else 3 + for i in 6: + var damage: float = float(spore.data.damage)*(.8 if id == "w08" else .6) if i < maximum else 0 + check(is_equal_approx(targets[i].max_hp-targets[i].hp,damage),id+" splash priority and unbuffed damage %d" % i) + check(primary.hp == primary.max_hp,id+" primary excluded from extra splash") + var archer := fixture("w05",80) + var a := fixture("e02",81,0,true) + var b := fixture("e02",82,0,true) + archer.target = a + for i in 3: archer.attack_component.step(archer,[archer,a,b],1) + archer.target = b + archer.attack_component.step(archer,[archer,a,b],1) + check(archer.attack_component.hit_count == 4 and b.dots.has("seed_burn"),"Target changes retain hit counters") + for unit: Node in fixtures: unit.free() + fixtures.clear() + +func _test_interface() -> void: + GameState.reset_match() + GameState.factions = ["wurzelbund","glutpakt"] + GameState.timed_build = false + GameState.select_mode(GameState.MODE_EXPEDITION) + main.hud._faction_pickers[0].select(1) + main.hud._faction_pickers[1].select(0) + main.hud._refresh() + await capture("menu") + main.hud._overlay_action.pressed.emit() + check(GameState.phase == GameState.Phase.BUILD,"Menu starts selected match") + WaveManager.advance(120) + check(GameState.phase == GameState.Phase.BUILD,"Untimed building does not start unexpectedly") + main.hud.request_wave_start() + check(GameState.phase == GameState.Phase.BUILD,"Empty formation gets build guidance") + check(not GameState.select_faction(0,"glutpakt"),"Faction locked during active match") + var before: Dictionary = EconomyManager.get_team(0) + check(not EconomyManager.apply_command(0,{"type":"build","type_id":"g01","cell":Vector2i.ZERO}).ok,"Foreign faction purchase rejected") + check(EconomyManager.get_team(0) == before,"Rejected order preserves complete economy") + main.hud._worker_button.pressed.emit() + check(EconomyManager.get_team(0).pending_workers == 1 and EconomyManager.get_team(0).workers == 1,"Worker waits until next build phase") + check(EconomyManager.get_team(0).sparks == 10,"Worker cannot produce on purchase") + main.hud._undo.pressed.emit() + check(EconomyManager.get_team(0) == before,"Undo cancels worker and refunds full price") + main.hud._starter_button.pressed.emit() + check(EconomyManager.get_team(0).gold == 35 and EconomyManager.get_team(0).roster.size() == 3,"Wurzelbund starter costs exactly 185") + check(main.hud._shop_buttons.has("w01") and not main.hud._shop_buttons.has("g01"),"Shop follows selected faction") + await capture("build") + main.hud.base_requested.emit() + check(main._base_view and main.camera.size == 14,"Base button focuses workers and crystal") + await capture("base") + main.hud.base_requested.emit() + check(not main._base_view,"Base button returns to formation") + main.hud.request_wave_start() + check(GameState.phase == GameState.Phase.COMBAT,"Ready starts combat") + check(not main.hud._cards.visible and main.hud._shop_panel.offset_top == -84,"Combat collapses shop and frees board space") + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: break + WaveManager.advance(1.0/60.0) + if step == 420: await capture("combat") + check(GameState.phase == GameState.Phase.RESULTS,"Real starter resolves first wave") + WaveManager.advance(60) + check(GameState.phase == GameState.Phase.RESULTS,"Untimed result waits for the player") + main.hud.request_wave_start() + check(GameState.wave == 2,"Next-wave button opens next build") + check(main.hud._cards.visible and main.hud._shop_panel.offset_top == -212,"Next build restores full shop") + var gold: int = EconomyManager.get_team(0).gold + main.hud._shop_buttons["w01"].pressed.emit() + check(is_instance_valid(main._ghost),"Build selection creates model preview") + var point: Vector2 = main.camera.unproject_position(Vector3(-14,0,3)) + # Real input route: this cell must be in the visible play area, not beneath HUD. + await get_tree().process_frame + var move := InputEventMouseMotion.new() + move.position = point + get_viewport().push_input(move,true) + await get_tree().process_frame + var click := InputEventMouseButton.new() + click.button_index = MOUSE_BUTTON_LEFT + click.position = point + click.pressed = true + get_viewport().push_input(click,true) + await get_tree().process_frame + click.pressed = false + get_viewport().push_input(click,true) + check(EconomyManager.get_team(0).gold == gold-50,"Visible-cell mouse input builds with real gold") + check(main.build_type.is_empty() and main.selected_uid > 0,"Single placement selects newly built unit") + check(not is_instance_valid(main._ghost),"Placement clears ghost") + await capture("selection") + if pictures: + var clip: ScrollContainer = main.hud._upgrade.get_parent().get_parent() + check(clip.get_global_rect().encloses(main.hud._upgrade.get_global_rect()), "Upgrade action visible without scrolling") + main.hud._undo.pressed.emit() + check(EconomyManager.get_team(0).gold == gold,"Undo refunds placed unit") + main.hud._worker_button.pressed.emit() + var pending: int = EconomyManager.get_team(0).pending_workers + main.hud.request_wave_start() + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: break + WaveManager.advance(1.0/60.0) + main.hud.request_wave_start() + check(pending == 1 and EconomyManager.get_team(0).workers == 2 and EconomyManager.get_team(0).pending_workers == 0,"Ordered worker activates once next wave") + check(EconomyManager.get_team(0).sparks == 40,"Two workers produce exactly twenty new sparks") + main.hud._send_picker.select(0) + main.hud._send_button.pressed.emit() + main.hud._refresh() + check(EconomyManager.reserved_sparks(0) == 20 and main.hud._sparks.text == "20","Sends and free-resource readout agree") + main.hud._cancel_send.pressed.emit() + check(EconomyManager.reserved_sparks(0) == 0,"Cancel releases reserved resources") + await capture("economy") + if pictures: + # Presentation-only stress fixture; the real economic state is untouched. + main.hud._refresh_send_queue({"send_queue":["s01","s02","s03","s04","s05","s01","s02","s03"]}) + await get_tree().process_frame + await get_tree().process_frame + check(main.hud._queue_scroll.get_global_rect().end.y <= get_viewport().get_visible_rect().end.y, "Eight send chips stay inside the screen") + check(main.hud._queue_scroll.size.y < 50, "Send queue scrolls horizontally instead of growing over controls") + main.hud._refresh_send_queue(EconomyManager.get_team(0)) + if pictures: + var original: Vector2i = get_window().size + get_window().size = Vector2i(1152,720) + await capture("minimum-window") + var rect := Rect2(Vector2.ZERO,get_viewport().get_visible_rect().size) + for control: Control in [main.hud._worker_button,main.hud._ready_button,main.hud._starter_button,main.hud._send_button,main.hud._shop_buttons.w09]: + check(rect.encloses(control.get_global_rect()),"Minimum window contains "+control.name) + get_window().size = original + GameState.reset_match() + GameState.factions = ["glutpakt","wurzelbund"] + GameState.timed_build = true + main._start_match() + main._starter() + check(EconomyManager.get_team(0).gold == 40,"Glutpakt starter keeps 180 gold price") + WaveManager.advance(45) + check(GameState.phase == GameState.Phase.COMBAT,"Optional timed mode still auto-starts") + main.hud.menu_requested.emit() + check(GameState.phase == GameState.Phase.MENU and EconomyManager.get_team(0).roster.is_empty(),"New game returns to faction choice and clears old match") + +func _play(title: String, own: String, rival: String, mode: String, screenshots: bool = false) -> void: + GameState.reset_match() + GameState.factions = [own,rival] + GameState.select_mode(mode) + GameState.timed_build = false + GameState.ai_level = GameState.AI_STANDARD + main.battle.render_enabled = pictures and screenshots + WaveManager.start_match() + var ai := AI.new() + var waves: Array = [] + for number: int in range(1,DataCatalog.wave_count()+1): + check(GameState.wave == number and GameState.phase == GameState.Phase.BUILD,title+" build %d" % number) + ai.plan(0,number,WaveManager.rival_snapshot(),GameState.last_reports[0],GameState.AI_STANDARD) + for team: int in range(2): + var state: Dictionary = EconomyManager.get_team(team) + check(state.gold >= 0 and EconomyManager.reserved_sparks(team) <= mini(state.sparks,EconomyManager.send_budget(number)),title+" paid commands %d/%d" % [number,team]) + for entry: Dictionary in state.roster: + check(str(entry.type_id).begins_with("w" if GameState.factions[team] == "wurzelbund" else "g"),title+" roster ownership") + WaveManager.ready_for_battle() + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: break + WaveManager.advance(1.0/60.0) + if screenshots and step == 360 and number in [5,10,15,20]: await capture("wave-%02d" % number) + check(GameState.phase in [GameState.Phase.RESULTS,GameState.Phase.GAME_OVER],title+" resolves %d" % number) + waves.append({"wave":number,"core_hp":GameState.core_hp.duplicate(),"seconds":main.battle.elapsed,"leaks":main.battle.leaks.duplicate(),"player_gold":EconomyManager.get_team(0).gold,"roster":EconomyManager.get_team(0).roster}) + if GameState.phase == GameState.Phase.GAME_OVER: break + WaveManager.ready_for_battle() + check(GameState.phase == GameState.Phase.GAME_OVER,title+" concludes") + if own == rival: + check(GameState.outcome == GameState.DRAW,title+" symmetric outcome") + check(GameState.wave == DataCatalog.wave_count(),title+" reaches finale with ordinary resources") + matches.append({"title":title,"outcome":GameState.outcome,"waves":waves}) + print("FACTION_MATCH: ",title," wave ",GameState.wave," cores ",GameState.core_hp) + +func capture(label: String) -> void: + if not pictures: return + await get_tree().process_frame + main.hud._refresh() + await get_tree().create_timer(.22).timeout + await RenderingServer.frame_post_draw + DirAccess.make_dir_recursive_absolute("user://phase10-captures") + check(get_viewport().get_texture().get_image().save_png("user://phase10-captures/"+label+".png") == OK,"capture "+label) diff --git a/scripts/qa/faction_test.gd.uid b/scripts/qa/faction_test.gd.uid new file mode 100644 index 0000000..418a4bc --- /dev/null +++ b/scripts/qa/faction_test.gd.uid @@ -0,0 +1 @@ +uid://bhv2jwnqkfjvk diff --git a/scripts/ui/components/choice_group.gd b/scripts/ui/components/choice_group.gd new file mode 100644 index 0000000..6f69403 --- /dev/null +++ b/scripts/ui/components/choice_group.gd @@ -0,0 +1,97 @@ +class_name ChoiceGroup +extends BoxContainer +## Segmented choice with the OptionButton surface used by tools and tests: +## select(index) changes the display only, item_selected fires on player input. +## Selection shows a filled diamond, a bright frame and brighter text, never colour alone. + +signal item_selected(index: int) + +const MARK_ON := preload("res://assets/ui/controls/choice_on.svg") +const MARK_OFF := preload("res://assets/ui/controls/choice_off.svg") + +var selected: int = -1 +var _buttons: Array[Button] = [] +var _marks: Array[TextureRect] = [] +var _group := ButtonGroup.new() + +func _init(horizontal: bool = true) -> void: + vertical = not horizontal + add_theme_constant_override("separation", 8) + +func add_option(title: String, detail: String = "", tooltip: String = "") -> Button: + var button := Button.new() + button.theme_type_variation = "ChoiceButton" + button.toggle_mode = true + button.button_group = _group + button.focus_mode = Control.FOCUS_ALL + button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + button.tooltip_text = tooltip + button.set_meta("title", title) + var row := HBoxContainer.new() + row.mouse_filter = Control.MOUSE_FILTER_IGNORE + row.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + row.offset_left = 14 + row.offset_right = -12 + row.add_theme_constant_override("separation", 12) + button.add_child(row) + var mark := TextureRect.new() + mark.texture = MARK_OFF + mark.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + mark.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + mark.custom_minimum_size = Vector2(16, 16) + mark.mouse_filter = Control.MOUSE_FILTER_IGNORE + mark.size_flags_vertical = Control.SIZE_SHRINK_CENTER + row.add_child(mark) + var text := VBoxContainer.new() + text.mouse_filter = Control.MOUSE_FILTER_IGNORE + text.alignment = BoxContainer.ALIGNMENT_CENTER + text.add_theme_constant_override("separation", 0) + text.size_flags_horizontal = Control.SIZE_EXPAND_FILL + row.add_child(text) + var heading := Label.new() + heading.text = title + heading.mouse_filter = Control.MOUSE_FILTER_IGNORE + heading.add_theme_font_size_override("font_size", 18) + text.add_child(heading) + if not detail.is_empty(): + var info := Label.new() + info.text = detail + info.theme_type_variation = "MutedLabel" + info.mouse_filter = Control.MOUSE_FILTER_IGNORE + info.add_theme_font_size_override("font_size", 15) + info.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + text.add_child(info) + var base_height: float = 62.0 if not detail.is_empty() else 46.0 + button.custom_minimum_size = Vector2(0, base_height) + # Buttons do not size to child controls; follow the wrapped text height instead. + row.minimum_size_changed.connect(func() -> void: + button.custom_minimum_size.y = maxf(base_height, row.get_combined_minimum_size().y + 20.0)) + var index: int = _buttons.size() + button.pressed.connect(func() -> void: + if selected != index: + select(index) + item_selected.emit(index)) + add_child(button) + _buttons.append(button) + _marks.append(mark) + return button + +func select(index: int) -> void: + if index < 0 or index >= _buttons.size(): + return + selected = index + for i: int in range(_buttons.size()): + _buttons[i].set_pressed_no_signal(i == index) + _marks[i].texture = MARK_ON if i == index else MARK_OFF + _buttons[i].set_meta("selected", i == index) + +func get_item_count() -> int: + return _buttons.size() + +func get_button(index: int) -> Button: + return _buttons[index] + +func focus_selected() -> void: + if selected >= 0 and selected < _buttons.size(): + _buttons[selected].grab_focus() diff --git a/scripts/ui/components/choice_group.gd.uid b/scripts/ui/components/choice_group.gd.uid new file mode 100644 index 0000000..fb0eb63 --- /dev/null +++ b/scripts/ui/components/choice_group.gd.uid @@ -0,0 +1 @@ +uid://cucy3kjesrteb diff --git a/scripts/ui/components/faction_choice.gd b/scripts/ui/components/faction_choice.gd new file mode 100644 index 0000000..aacf4e0 --- /dev/null +++ b/scripts/ui/components/faction_choice.gd @@ -0,0 +1,143 @@ +class_name FactionChoice +extends HBoxContainer +## Selectable Bund cards with the OptionButton surface used by tools and tests. +## Index order follows DataCatalog.FACTIONS. Selected cards carry a text badge, +## a double frame and full-colour emblems; the others show a quiet "Wählen" hint. + +signal item_selected(index: int) + +# Play-style summaries are taken from DataCatalog ability texts; no invented mechanics. +const PROFILES: Dictionary = { + "glutpakt": {"emblem": "res://assets/ui/emblems/glutpakt.svg", "motto": "Schutz, Brand und Flächenschaden", + "facts": ["Basaltschilde senken erlittenen Schaden, vor allem zu Kampfbeginn", "Glutklingen setzen bei jedem 3. Treffer Brand", + "Aschenwerfer treffen mehrere Ziele, Herdhüter stärken Verbündete"]}, + "wurzelbund": {"emblem": "res://assets/ui/emblems/wurzelbund.svg", "motto": "Heilung, Ranken und Keimbrand", + "facts": ["Holzpanzer heilen sich, sobald sie verwundet sind", "Ranken verlangsamen Gegner", + "Heiler versorgen Verbündete in 4 bis 4,5 m, Samenschützen setzen Keimbrand"]}, +} + +var selected: int = -1 +var cards: Array[Button] = [] +var _badges: Array[Control] = [] +var _hints: Array[Label] = [] +var _emblems: Array[TextureRect] = [] +var _group := ButtonGroup.new() + +func _ready() -> void: + add_theme_constant_override("separation", 16) + for id: String in DataCatalog.FACTIONS: + _make_card(id) + +func _make_card(id: String) -> void: + var profile: Dictionary = PROFILES[id] + var card := Button.new() + card.name = "Card_" + id + card.theme_type_variation = "FactionCard" + card.toggle_mode = true + card.button_group = _group + card.focus_mode = Control.FOCUS_ALL + card.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + card.size_flags_horizontal = Control.SIZE_EXPAND_FILL + card.custom_minimum_size = Vector2(220, 236) + card.tooltip_text = "%s wählen · Startformation %d Gold" % [DataCatalog.FACTION_NAMES[id], starter_cost(id)] + var content := VBoxContainer.new() + content.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + content.offset_left = 16 + content.offset_right = -16 + content.offset_top = 18 + content.offset_bottom = -14 + content.add_theme_constant_override("separation", 6) + card.add_child(content) + var emblem := TextureRect.new() + emblem.texture = load(profile.emblem) + emblem.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + emblem.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + emblem.custom_minimum_size = Vector2(84, 84) + emblem.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(emblem) + var title := Label.new() + title.text = DataCatalog.FACTION_NAMES[id] + title.theme_type_variation = "CardTitleLabel" + title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + title.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(title) + var motto := Label.new() + motto.text = profile.motto + motto.theme_type_variation = "LoreLabel" + motto.add_theme_font_size_override("font_size", 18) + motto.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + motto.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + motto.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(motto) + var spacer := Control.new() + spacer.size_flags_vertical = Control.SIZE_EXPAND_FILL + spacer.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(spacer) + var foot := CenterContainer.new() + foot.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(foot) + var states := HBoxContainer.new() + states.mouse_filter = Control.MOUSE_FILTER_IGNORE + foot.add_child(states) + var badge := PanelContainer.new() + badge.theme_type_variation = "BadgePanel" + badge.mouse_filter = Control.MOUSE_FILTER_IGNORE + var badge_row := HBoxContainer.new() + badge_row.mouse_filter = Control.MOUSE_FILTER_IGNORE + badge_row.add_theme_constant_override("separation", 6) + badge.add_child(badge_row) + var mark := TextureRect.new() + mark.texture = preload("res://assets/ui/controls/choice_on.svg") + mark.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + mark.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + mark.custom_minimum_size = Vector2(12, 12) + mark.modulate = Color("1a120a") + mark.mouse_filter = Control.MOUSE_FILTER_IGNORE + badge_row.add_child(mark) + var badge_text := Label.new() + badge_text.text = "DEIN BUND" + badge_text.theme_type_variation = "BadgeLabel" + badge_text.mouse_filter = Control.MOUSE_FILTER_IGNORE + badge_row.add_child(badge_text) + states.add_child(badge) + var hint := Label.new() + hint.text = "Wählen" + hint.theme_type_variation = "MutedLabel" + hint.add_theme_font_size_override("font_size", 14) + hint.mouse_filter = Control.MOUSE_FILTER_IGNORE + states.add_child(hint) + content.minimum_size_changed.connect(func() -> void: + card.custom_minimum_size.y = maxf(236.0, content.get_combined_minimum_size().y + 32.0)) + var index: int = cards.size() + card.pressed.connect(func() -> void: + if selected != index: + select(index) + item_selected.emit(index)) + add_child(card) + cards.append(card) + _badges.append(badge) + _hints.append(hint) + _emblems.append(emblem) + +static func starter_cost(id: String) -> int: + var ids: Array[String] = DataCatalog.faction_ids(id) + return int(DataCatalog.UNITS[ids[0]].cost + DataCatalog.UNITS[ids[1]].cost + DataCatalog.UNITS[ids[2]].cost) + +func select(index: int) -> void: + if index < 0 or index >= cards.size(): + return + selected = index + for i: int in range(cards.size()): + var on: bool = i == index + cards[i].set_pressed_no_signal(on) + _badges[i].visible = on + _hints[i].visible = not on + _emblems[i].modulate = Color.WHITE if on else Color(.72, .70, .66) + +func focus_selected() -> void: + if selected >= 0: + cards[selected].grab_focus() + +func selected_id() -> String: + return DataCatalog.FACTIONS[selected] if selected >= 0 else "" diff --git a/scripts/ui/components/faction_choice.gd.uid b/scripts/ui/components/faction_choice.gd.uid new file mode 100644 index 0000000..8c11e7c --- /dev/null +++ b/scripts/ui/components/faction_choice.gd.uid @@ -0,0 +1 @@ +uid://cpf26g37y1foq diff --git a/scripts/ui/hud.gd b/scripts/ui/hud.gd new file mode 100644 index 0000000..9b4d937 --- /dev/null +++ b/scripts/ui/hud.gd @@ -0,0 +1,894 @@ +extends Control +## Presentation only: emits player commands and reads snapshots. + +signal command_requested(command: Dictionary) +signal build_selected(type_id: String) +signal move_requested +signal base_requested +signal focus_requested +signal menu_requested +signal new_match_requested +signal starter_requested +signal cancel_requested +signal ready_requested + +const INK := Color("#0b1016") +const PANEL := Color("#101a22") +const TEXT := Color("#f2f6f4") +const MUTED := Color("#9bb0aa") +const GOLD := Color("#f0d090") +const GOLD_DEEP := Color("#c9a05a") +const TEAL := Color("#7fe8c8") +const TEAL_DEEP := Color("#2a8f7a") +const CORAL := Color("#f0a888") +const VIOLET := Color("#b8a0e8") + +var selected_uid: int = -1 +var build_type: String = "" +var viewed_team: int = 0 +var model_inspector: ColorRect +var _inspect_model: Button +var settings_panel: ColorRect +var _settings_paused: bool = false +var _settings_focus: Control +var _volume_slider: HSlider +var _mute_check: CheckButton +var _follow_check: CheckButton +var _fullscreen_check: CheckButton +var _camera_status: Label +var _boss_bar: ProgressBar +var _boss_label: Label +var _phase: Label +var _timer: Label +var _gold: Label +var _sparks: Label +var _income: Label +var _workers: Label +var _core_labels: Array = [] +var _core_bars: Array = [] +var _wave_title: Label +var _wave_body: Label +var _selection_icon: TextureRect +var _selection_types: HBoxContainer +var _selection_title: Label +var _selection_body: Label +var _upgrade: Button +var _sell: Button +var _move: Button +var _priority: OptionButton +var _worker_button: Button +var _ready_button: Button +var _pause_button: Button +var _speed_button: Button +var _front_button: Button +var _undo: Button +var _starter_button: Button +var _cards: HBoxContainer +var _shop_faction: String = "" +var _faction_label: Label +var _worker_info: Label +var _step_hint: Label +var _faction_pickers: Array = [] +var _timed_picker: CheckButton +var _shop_buttons: Dictionary = {} +var _send_picker: OptionButton +var _send_button: Button +var _cancel_send: Button +var _send_info: Label +var _toast: Label +var _toast_left: float = 0.0 +## Phase 20A: the title menu and match setup live in MainMenu. These names remain the +## entry points used by tools and tests; they point at OptionButton-compatible parts. +var main_menu: MainMenu +var _overlay: Control +var _overlay_title: Label +var _overlay_action: Button +var _ai_picker: ChoiceGroup +var _mode_picker: ChoiceGroup +var _reduced_check: CheckButton +var _summary: Label +var _queue_scroll: ScrollContainer +var _queue_row: HBoxContainer +var _queue_signature: String = "@" +var _refresh_left: float = 0.0 +var _shop_panel: PanelContainer +var _wave_progress: ProgressBar +var _context_panel: PanelContainer +var _context_column: VBoxContainer +var _game_panels: Array[Control] = [] +var _logo_label: Label + +const SEND_SHORT_NAMES: Dictionary = { + "s01": "Späher", "s02": "Rost", "s03": "Dunst", "s04": "Keil", "s05": "Riss"} +const MATRIX_TOOLTIP: String = "Schadensmatrix (Zeile → Spalte):\nKlinge: 130 % gegen Leicht · 75 % gegen Schwer\nDurchschlag: 130 % gegen Schwer · 75 % gegen Ätherisch\nImpuls: 130 % gegen Ätherisch · 75 % gegen Leicht" + + +func _ready() -> void: + mouse_filter = Control.MOUSE_FILTER_IGNORE + theme = _make_theme() + _make_header() + _make_sidebar() + _make_footer() + _make_overlay() + _make_settings() + model_inspector = preload("res://scripts/ui/model_inspector.gd").new() + add_child(model_inspector) + GameState.phase_changed.connect(_phase_changed) + WaveManager.wave_settled.connect(_show_summary) + _phase_changed(GameState.phase) + + +func _style(color: Color, border: Color = Color.TRANSPARENT, width: int = 0) -> StyleBoxFlat: + var box := StyleBoxFlat.new() + box.bg_color = color + box.border_color = border + box.set_border_width_all(width) + box.set_corner_radius_all(14) + box.anti_aliasing = true + box.content_margin_left = 16 + box.content_margin_right = 16 + box.content_margin_top = 10 + box.content_margin_bottom = 10 + return box + + +func _glass(bg: Color = Color(.05, .09, .12, .88), border: Color = Color(.45, .85, .75, .22)) -> StyleBoxFlat: + var box := _style(bg, border, 1) + box.set_corner_radius_all(16) + box.shadow_color = Color(0, 0, 0, .45) + box.shadow_size = 14 + box.shadow_offset = Vector2(0, 6) + box.content_margin_left = 18 + box.content_margin_right = 18 + box.content_margin_top = 12 + box.content_margin_bottom = 12 + return box + + +func _gold_button() -> StyleBoxFlat: + var box := _style(Color("#e8c57a"), Color("#ffe2a8"), 1) + box.set_corner_radius_all(12) + box.shadow_color = Color(.95, .75, .35, .35) + box.shadow_size = 16 + box.shadow_offset = Vector2(0, 2) + box.content_margin_top = 12 + box.content_margin_bottom = 12 + return box + + +func _make_theme() -> Theme: + var result := Theme.new() + result.default_font_size = 15 + var modern_font := FontVariation.new() + modern_font.base_font = preload("res://assets/fonts/Cantarell-VF.otf") + modern_font.variation_opentype = {"wght": 550.0} + result.default_font = modern_font + result.set_color("font_color", "Label", TEXT) + result.set_color("font_color", "Button", TEXT) + result.set_color("font_hover_color", "Button", Color.WHITE) + result.set_color("font_disabled_color", "Button", Color("#6a807c")) + result.set_stylebox("normal", "Button", _style(Color("#1c2c36"), Color("#3d5a58"), 1)) + result.set_stylebox("hover", "Button", _style(Color("#284852"), TEAL, 1)) + result.set_stylebox("pressed", "Button", _style(Color("#1f3c40"), TEAL_DEEP, 2)) + result.set_stylebox("focus", "Button", _style(Color(0, 0, 0, 0), GOLD, 2)) + result.set_stylebox("disabled", "Button", _style(Color("#152028"))) + result.set_stylebox("normal", "PanelContainer", _glass()) + result.set_constant("separation", "VBoxContainer", 10) + result.set_constant("separation", "HBoxContainer", 12) + result.set_color("font_color", "OptionButton", TEXT) + result.set_stylebox("normal", "OptionButton", _style(Color("#1c2c36"), Color("#3d5a58"), 1)) + result.set_stylebox("hover", "OptionButton", _style(Color("#284852"), TEAL, 1)) + result.set_stylebox("focus", "OptionButton", _style(Color("#284852"), GOLD, 1)) + var popup := _glass(Color(.06, .10, .14, .97), Color(.4, .7, .65, .3)) + result.set_stylebox("panel", "PopupMenu", popup) + result.set_color("font_color", "PopupMenu", TEXT) + result.set_color("font_hover_color", "PopupMenu", GOLD) + return result + + +func _label(text_value: String, size: int, parent: Node, color: Color = TEXT) -> Label: + var label := Label.new() + label.text = text_value + label.add_theme_font_size_override("font_size", size) + label.add_theme_color_override("font_color", color) + label.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(label) + return label + + +func _button(text_value: String, action: Callable, parent: Node) -> Button: + var button := Button.new() + button.text = text_value + button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + button.pressed.connect(action) + parent.add_child(button) + return button + + +func _panel(parent: Node) -> PanelContainer: + var panel := PanelContainer.new() + parent.add_child(panel) + return panel + + +func _make_header() -> void: + var header := _panel(self) + _game_panels.append(header) + header.set_anchors_and_offsets_preset(Control.PRESET_TOP_WIDE) + header.offset_left = 18 + header.offset_top = 16 + header.offset_right = -18 + header.offset_bottom = 92 + var row := HBoxContainer.new() + row.add_theme_constant_override("separation", 18) + header.add_child(row) + var title := VBoxContainer.new() + title.custom_minimum_size.x = 185 + title.size_flags_vertical = Control.SIZE_SHRINK_CENTER + row.add_child(title) + var logo := _label("S A U M W A C H T", 22, title, Color("#f6e6b8")) + _logo_label = logo + _faction_label = _label("", 11, title, TEAL) + var phase_box := VBoxContainer.new() + phase_box.custom_minimum_size.x = 164 + phase_box.size_flags_vertical = Control.SIZE_SHRINK_CENTER + row.add_child(phase_box) + _phase = _label("VORBEREITUNG", 11, phase_box, TEAL) + _timer = _label("", 22, phase_box) + _wave_progress = ProgressBar.new() + _wave_progress.custom_minimum_size.y = 3 + _wave_progress.show_percentage = false + var progress_fill := _style(TEAL) + var progress_back := _style(Color("2c403e")) + for style: StyleBoxFlat in [progress_fill, progress_back]: + style.content_margin_top = 0 + style.content_margin_bottom = 0 + _wave_progress.add_theme_stylebox_override("fill", progress_fill) + _wave_progress.add_theme_stylebox_override("background", progress_back) + phase_box.add_child(_wave_progress) + _gold = _metric(row, "GOLD", GOLD, "res_gold") + _sparks = _metric(row, "FUNKEN", TEAL, "res_sparks") + _income = _metric(row, "PRO WELLE", GOLD, "res_income") + _workers = _metric(row, "ARBEITER", TEXT, "worker") + var spacer := Control.new() + spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL + row.add_child(spacer) + var controls := VBoxContainer.new() + controls.add_theme_constant_override("separation", 3) + row.add_child(controls) + var buttons := HBoxContainer.new() + buttons.add_theme_constant_override("separation", 6) + controls.add_child(buttons) + _pause_button = _button("Pause [P]", toggle_pause, buttons) + _speed_button = _button("1×", _toggle_speed, buttons) + _button("Optionen", toggle_settings, buttons).tooltip_text = "Einstellungen & Steuerung [F1]" + _front_button = _button("Rivalen beobachten [Tab]", func(): focus_requested.emit(), controls) + for button: Node in buttons.get_children(): + button.add_theme_font_size_override("font_size", 12) + _front_button.add_theme_font_size_override("font_size", 12) + + +func _metric(parent: Node, caption: String, color: Color, icon_id: String) -> Label: + var panel := PanelContainer.new() + panel.add_theme_stylebox_override("panel", _glass(Color(.08, .13, .16, .55), Color(.4, .7, .65, .14))) + panel.custom_minimum_size.x = 118 + parent.add_child(panel) + var row := HBoxContainer.new() + row.add_theme_constant_override("separation", 9) + panel.add_child(row) + _icon(icon_id, row, Vector2(24,24)) + var column := VBoxContainer.new() + column.add_theme_constant_override("separation", 0) + row.add_child(column) + _label(caption, 10, column, MUTED) + return _label("—", 24, column, color) + + +func _make_sidebar() -> void: + var guide := _panel(self) + guide.position = Vector2(22, 110) + guide.add_theme_stylebox_override("panel", _style(Color(.05,.08,.09,.86))) + var location := VBoxContainer.new() + guide.add_child(location) + _game_panels.append(guide) + _label("DIE GRÜNE KLUFT / DEINE FRONT", 11, location, TEAL) + _step_hint = _label("", 16, location) + _camera_status = _label("Q / E Drehen · R Zurücksetzen · F1 Hilfe", 12, location, MUTED) + _boss_label = _label("", 17, location, CORAL) + _boss_bar = ProgressBar.new() + _boss_bar.custom_minimum_size = Vector2(285, 13) + _boss_bar.show_percentage = false + _boss_bar.add_theme_stylebox_override("background", _style(Color("#101d25"))) + _boss_bar.add_theme_stylebox_override("fill", _style(CORAL)) + location.add_child(_boss_bar) + _boss_bar.visible = false + var sidebar := _panel(self) + _context_panel = sidebar + _game_panels.append(sidebar) + sidebar.anchor_left = 1.0 + sidebar.anchor_right = 1.0 + sidebar.anchor_bottom = 0.0 + sidebar.offset_left = -348 + sidebar.offset_right = -20 + sidebar.offset_top = 108 + sidebar.offset_bottom = 504 + var scroll := ScrollContainer.new() + scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + sidebar.add_child(scroll) + var column := VBoxContainer.new() + column.size_flags_horizontal = Control.SIZE_EXPAND_FILL + scroll.add_child(column) + _context_column = column + column.add_theme_constant_override("separation", 6) + _ready_button = _button("KAMPF STARTEN [Leertaste]", request_wave_start, column) + _ready_button.custom_minimum_size.y = 52 + _ready_button.add_theme_font_size_override("font_size", 15) + _ready_button.add_theme_stylebox_override("normal", _gold_button()) + _ready_button.add_theme_stylebox_override("hover", _gold_button()) + _ready_button.add_theme_stylebox_override("pressed", _gold_button()) + _ready_button.add_theme_color_override("font_color", INK) + _ready_button.add_theme_color_override("font_hover_color", INK) + for team in range(2): + var color := TEAL if team == 0 else CORAL + var caption := _label("DEIN KERN" if team == 0 else "RIVALENKERN", 13, column, color) + _core_labels.append(caption) + var bar := ProgressBar.new() + bar.max_value = 3000 + bar.value = 3000 + bar.show_percentage = false + bar.custom_minimum_size.y = 7 + var background := _style(Color("#101d25")) + var fill := _style(color) + for style: StyleBoxFlat in [background, fill]: + style.content_margin_top = 0 + style.content_margin_bottom = 0 + bar.add_theme_stylebox_override("background", background) + bar.add_theme_stylebox_override("fill", fill) + column.add_child(bar) + _core_bars.append(bar) + column.add_child(HSeparator.new()) + _wave_title = _label("NÄCHSTE WELLE", 13, column, GOLD) + _wave_title.mouse_filter = Control.MOUSE_FILTER_STOP + _wave_body = _label("", 14, column, MUTED) + _wave_body.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _wave_body.custom_minimum_size.x = 278 + column.add_child(HSeparator.new()) + var selected_row := HBoxContainer.new() + column.add_child(selected_row) + _selection_icon = _icon("", selected_row, Vector2(64,64)) + _selection_icon.visible = false + _selection_title = _label("DEINE FORMATION", 18, selected_row) + _selection_title.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _selection_types = HBoxContainer.new() + column.add_child(_selection_types) + _selection_title.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _selection_body = _label("", 14, column, MUTED) + _selection_body.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _selection_body.custom_minimum_size = Vector2(278, 45) + _upgrade = _button("Aufwerten", _upgrade_selected, column) + var actions := HBoxContainer.new() + column.add_child(actions) + _move = _button("Versetzen", func(): move_requested.emit(), actions) + _sell = _button("Verkaufen", func(): _emit_selected("sell"), actions) + _priority = OptionButton.new() + for title in ["Nächstes Ziel", "Niedrigste HP", "Höchste maximale HP"]: + _priority.add_item(title) + _priority.item_selected.connect(func(index: int): + command_requested.emit({"type": "target", "uid": selected_uid, "policy": index})) + column.add_child(_priority) + _inspect_model = _button("3D-Modell ansehen [V]", inspect_selected_model, column) + _summary = _label("", 13, column, TEAL) + _summary.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + + +func _make_footer() -> void: + var footer := _panel(self) + _shop_panel = footer + _game_panels.append(footer) + footer.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_WIDE) + footer.offset_left = 16 + footer.offset_right = -364 + footer.offset_top = -212 + footer.offset_bottom = -18 + var shop := VBoxContainer.new() + shop.add_theme_constant_override("separation", 7) + footer.add_child(shop) + var heading := HBoxContainer.new() + shop.add_child(heading) + var title := _label("WÄCHTER / WÄHLEN & PLATZIEREN", 12, heading, TEAL) + title.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _starter_button = _button("Startformation", func(): starter_requested.emit(), heading) + _starter_button.tooltip_text = "Stellt drei bezahlte Wächter auf: Tank und Nahkämpfer vorn, Schütze dahinter." + _undo = _button("↶ Rückgängig", func(): command_requested.emit({"type": "undo"}), heading) + _cards = HBoxContainer.new() + _cards.add_theme_constant_override("separation", 8) + shop.add_child(_cards) + _rebuild_shop() + _toast = _label("", 13, shop, MUTED) + _toast.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + var economy := _panel(self) + _game_panels.append(economy) + economy.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_RIGHT) + economy.offset_left = -348 + economy.offset_right = -20 + economy.offset_top = -300 + economy.offset_bottom = -18 + var column := VBoxContainer.new() + column.add_theme_constant_override("separation", 5) + economy.add_child(column) + var row := HBoxContainer.new() + column.add_child(row) + _label("BASIS & NACHschub".to_upper(), 12, row, TEAL).size_flags_horizontal = Control.SIZE_EXPAND_FILL + _button("Ansehen [C]", func(): base_requested.emit(), row) + _worker_button = _button("Arbeiter ausbilden", func(): command_requested.emit({"type": "worker"}), column) + _worker_button.icon = AssetLibrary.icon("worker") + _worker_button.add_theme_constant_override("icon_max_width", 25) + _worker_info = _label("", 12, column, MUTED) + _worker_info.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + column.add_child(HSeparator.new()) + _send_picker = OptionButton.new() + for send_id in ["s01", "s02", "s03", "s04", "s05"]: + var data: Dictionary = DataCatalog.get_send(send_id, 1) + _send_picker.add_icon_item(AssetLibrary.icon(send_id), "%s · %d F · +%d G/Welle" % [data.display_name, data.cost, data.income_gain]) + _send_picker.add_theme_constant_override("icon_max_width", 22) + _send_picker.get_popup().add_theme_constant_override("icon_max_width", 22) + column.add_child(_send_picker) + var send_row := HBoxContainer.new() + column.add_child(send_row) + _send_button = _button("Zum Rivalen senden", _queue_send, send_row) + _cancel_send = _button("↶", _cancel_last_send, send_row) + _cancel_send.tooltip_text = "Letzten Söldner entfernen; Funken zurückgeben" + _send_info = _label("", 12, column, MUTED) + _queue_scroll = ScrollContainer.new() + _queue_scroll.custom_minimum_size.y = 36 + _queue_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + column.add_child(_queue_scroll) + _queue_row = HBoxContainer.new() + _queue_row.add_theme_constant_override("separation", 4) + _queue_scroll.add_child(_queue_row) + +func _rebuild_shop() -> void: + if _shop_faction == GameState.factions[0]: + return + _shop_faction = GameState.factions[0] + _shop_buttons.clear() + for child: Node in _cards.get_children(): + child.free() + var index: int = 0 + for type_id: String in DataCatalog.base_ids(): + var data: Dictionary = DataCatalog.get_unit(type_id) + var button := _button("", func(): build_selected.emit(type_id), _cards) + button.custom_minimum_size = Vector2(0, 121) + button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + var content := VBoxContainer.new() + content.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_theme_constant_override("separation", 1) + content.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + content.offset_left = 10 + content.offset_right = -10 + content.offset_top = 4 + content.offset_bottom = -4 + button.add_child(content) + var top := HBoxContainer.new() + top.mouse_filter = Control.MOUSE_FILTER_IGNORE + content.add_child(top) + _icon(type_id, top, Vector2(68, 68)) + var price := VBoxContainer.new() + price.mouse_filter = Control.MOUSE_FILTER_IGNORE + top.add_child(price) + _label("%d G" % data.cost, 20, price, GOLD) + _label("[ %d ]" % (index+1), 12, price, MUTED) + _label(data.display_name, 15, content).horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _label(DataCatalog.ROLES[index], 12, content, TEAL).horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + button.tooltip_text = "%s · %s +%d HP · %d Schaden/s · %.1f m +%s" % [DataCatalog.DAMAGE_NAMES[data.attack_type], DataCatalog.ARMOR_NAMES[data.armor_type], data.max_hp, data.damage, data.attack_range, data.ability_description] + _shop_buttons[type_id] = button + index += 1 + + +func _make_overlay() -> void: + main_menu = MainMenu.new() + add_child(main_menu) + _overlay = main_menu + _overlay_action = main_menu.start_button + _overlay_title = main_menu.length_summary + _faction_pickers = [main_menu.faction_choice, main_menu.rival_choice] + _mode_picker = main_menu.mode_choice + _ai_picker = main_menu.ai_choice + _timed_picker = main_menu.timed_toggle + main_menu.start_requested.connect(func() -> void: new_match_requested.emit()) + main_menu.settings_requested.connect(toggle_settings) + main_menu.models_requested.connect(inspect_selected_model) + main_menu.quit_requested.connect(func() -> void: Soundscape.quit_game()) + main_menu.selection_changed.connect(_rebuild_shop) + + +func _process(delta: float) -> void: + _toast_left -= delta + _refresh_left -= delta + if _refresh_left <= 0: + _refresh_left = 0.12 + _refresh() + + +func _refresh() -> void: + var team: Dictionary = EconomyManager.get_team(0) + if team.is_empty(): + return + _rebuild_shop() + if GameState.phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER] and is_instance_valid(main_menu): + # Match options can also change outside the menu (tools, tests); keep the display honest. + main_menu.sync() + _faction_label.text = DataCatalog.FACTION_NAMES[GameState.factions[0]].to_upper() + " / " + ("DEINE FRONT" if viewed_team == 0 else "RIVALENFRONT") + var building := GameState.phase == GameState.Phase.BUILD + _wave_progress.max_value = DataCatalog.wave_count() + _wave_progress.value = maxi(0, GameState.wave - 1) + _phase.text = GameState.phase_name() + (" · PAUSIERT" if GameState.paused else "") + _timer.text = "%02d / %02d · %02d s" % [maxi(1, GameState.wave), DataCatalog.wave_count(), ceili(WaveManager.remaining)] + if not GameState.timed_build and GameState.phase in [GameState.Phase.BUILD, GameState.Phase.RESULTS]: + _timer.text = "Welle %02d / %02d" % [maxi(1, GameState.wave), DataCatalog.wave_count()] + _gold.text = str(team.gold) + _sparks.text = "%d" % (int(team.sparks) - EconomyManager.reserved_sparks(0)) + _sparks.tooltip_text = "Freie Funken. Vorgemerkte Söldner sind bereits abgezogen." + _income.text = "+%d" % team.income + _workers.text = "%d%s" % [team.workers, (" +%d" % team.pending_workers) if team.pending_workers else ""] + _workers.tooltip_text = "Aktive Arbeiter + bestellte Arbeiter. Je 10 Funken zu Beginn der nächsten Bauphase." + for side in range(2): + _core_labels[side].text = "%s %d / 3000" % [ + "DEIN KERN" if side == 0 else "RIVALENKERN", GameState.core_hp[side]] + _core_bars[side].value = GameState.core_hp[side] + _pause_button.text = "Fortsetzen [P]" if GameState.paused else "Pause [P]" + _speed_button.text = "%d×" % GameState.speed + _front_button.text = "Eigene Front [Tab]" if viewed_team else "Rivalen beobachten [Tab]" + var w: int = maxi(1, GameState.wave) + var wave_data: Dictionary = DataCatalog.get_wave(w) + _wave_title.text = "%02d · %s" % [w, str(wave_data.get("title", "Welle"))] + _wave_body.text = str(wave_data.get("description", "")) + "\n\n" + DataCatalog.wave_hint(w) + _wave_title.tooltip_text = _wave_body.text + for type_id in _shop_buttons: + var data: Dictionary = DataCatalog.get_unit(type_id) + var button: Button = _shop_buttons[type_id] + button.disabled = not building or team.gold < data.cost + button.modulate = Color.WHITE + if build_type == type_id: + button.add_theme_stylebox_override("normal", _style(Color("2a5048"), TEAL, 2)) + else: + var card := _style(Color("1a2c34"), Color("3a5558"), 1) + card.set_corner_radius_all(16) + card.shadow_color = Color(0, 0, 0, .3) + card.shadow_size = 6 + button.add_theme_stylebox_override("normal", card) + _starter_button.disabled = not building or not team.roster.is_empty() or team.gold < DataCatalog.starter_cost() + _starter_button.text = "Startformation · %d G" % DataCatalog.starter_cost() + _undo.disabled = not building + _worker_button.text = "Arbeiter ausbilden · %d Gold" % EconomyManager.worker_cost(0) + _worker_button.disabled = not building or w >= DataCatalog.wave_count() or team.workers + team.pending_workers >= 8 or team.gold < EconomyManager.worker_cost(0) + _worker_info.text = "%d / 8 aktiv%s · +%d Funken / Welle\nNeue Arbeiter produzieren ab Welle %d." % [team.workers, " (+%d bestellt)" % team.pending_workers if team.pending_workers > 0 else "", int(team.workers) * 10, w+1] + if w >= DataCatalog.wave_count(): + _worker_info.text = "Letzte Welle · Gold jetzt in Wächter investieren." + var send_cost: int = int(DataCatalog.SENDS["s%02d" % (_send_picker.selected + 1)].cost) + _send_button.disabled = not building or w < 3 or team.send_queue.size() >= 8 or mini(int(team.sparks), EconomyManager.send_budget(w)) - EconomyManager.reserved_sparks(0) < send_cost + _cancel_send.disabled = not building or team.send_queue.is_empty() + _send_picker.disabled = not building or w < 3 + _send_info.text = "%d / 8 geplant · %d / %d F Budget" % [ + team.send_queue.size(), EconomyManager.reserved_sparks(0), EconomyManager.send_budget(w)] + if w < 3: + _send_info.text = "Söldner verfügbar ab Welle 3" + _refresh_send_queue(team) + _ready_button.disabled = not building and GameState.phase != GameState.Phase.RESULTS + _ready_button.text = "NÄCHSTE WELLE [Leertaste]" if GameState.phase == GameState.Phase.RESULTS else ("KAMPF LÄUFT …" if GameState.phase == GameState.Phase.COMBAT else "KAMPF STARTEN [Leertaste]") + _step_hint.text = ("Erst Startformation setzen oder Wächter wählen." if team.roster.is_empty() else ("Platzieren → Aufwerten → Kampf starten" if build_type.is_empty() else "Freies Feld anklicken · Rechtsklick bricht ab")) if building else ("Welle beendet · Abrechnung rechts" if GameState.phase == GameState.Phase.RESULTS else "Deine Formation kämpft automatisch") + _refresh_selection(team, building) + if is_instance_valid(_context_column): + _context_panel.size.y = minf(_context_column.get_combined_minimum_size().y + 24, size.y - 422) + if _toast_left <= 0: + _toast.text = "1–5 Bauen · Linksklick Auswählen · Rechtsklick Abbrechen · Mausrad Zoom" + _toast.add_theme_color_override("font_color", MUTED) + + +func _refresh_selection(team: Dictionary, building: bool) -> void: + var selected: Dictionary = {} + for entry in team.roster: + if entry.uid == selected_uid: + selected = entry + break + var has_selection := not selected.is_empty() + _wave_title.visible = not has_selection + _summary.visible = not has_selection + _wave_body.visible = not has_selection + _inspect_model.visible = has_selection + _upgrade.visible = has_selection + _move.visible = has_selection + _sell.visible = has_selection + _priority.visible = has_selection + if not has_selection: + _selection_icon.visible = not build_type.is_empty() + _selection_icon.texture = AssetLibrary.icon(build_type) + _selection_types.visible = false + _selection_title.text = "DEINE FORMATION" + _selection_body.text = "%d / 48 Plätze · Tank vorn, Schützen dahinter.\nKlicke einen Wächter an, um ihn aufzuwerten." % team.roster.size() + if not build_type.is_empty(): + var candidate: Dictionary = DataCatalog.get_unit(build_type) + _selection_title.text = candidate.display_name + _selection_body.text = "%d Gold · %d HP · %d Schaden/s\n%s\n\nLinksklick setzt einen Wächter. Shift setzt mehrere." % [candidate.cost, candidate.max_hp, candidate.damage, candidate.ability_description] + return + var data: Dictionary = DataCatalog.get_unit(selected.type_id) + _selection_icon.visible = true + _selection_icon.texture = AssetLibrary.icon(str(data.id)) + _selection_types.visible = true + _refresh_type_icons(data) + _selection_title.text = data.display_name + _selection_body.text = "%d HP · %d Grund-DPS · %.1f m\n\n%s" % [ + data.max_hp, data.damage, data.attack_range, + str(data.get("ability_description", ""))] + _selection_body.tooltip_text = "%s · %s" % [data.display_name, MATRIX_TOOLTIP] + var upgrade_id: String = str(data.get("upgrade_id", "")) + var upgraded: Dictionary = DataCatalog.get_unit(upgrade_id) if not upgrade_id.is_empty() else {} + _upgrade.disabled = not building or upgraded.is_empty() or team.gold < int(upgraded.get("cost", 0)) + _upgrade.text = "Vollständig aufgewertet" if upgraded.is_empty() else "AUFWERTEN · %d GOLD\n%s" % [upgraded.cost, upgraded.display_name] + _upgrade.add_theme_font_size_override("font_size", 13) + _upgrade.tooltip_text = "" if upgraded.is_empty() else "%d → %d HP · %d → %d Schaden/s\n%s%s" % [data.max_hp, upgraded.max_hp, data.damage, upgraded.damage, upgraded.ability_description, "\nEs fehlen %d Gold." % (int(upgraded.cost)-int(team.gold)) if team.gold < int(upgraded.cost) else ""] + _sell.text = "Verkaufen · %d G" % floori(selected.invested * 0.75) + _sell.disabled = not building + _move.disabled = not building + _priority.disabled = not building + _priority.select(selected.target_policy) + + +func _refresh_send_queue(team: Dictionary) -> void: + var signature: String = ",".join(PackedStringArray(team.send_queue)) + if signature == _queue_signature: + return + _queue_signature = signature + for child in _queue_row.get_children(): + child.free() + var index := 0 + for send_id: String in team.send_queue: + var chip := _button(SEND_SHORT_NAMES.get(send_id, send_id), + func(): command_requested.emit({"type": "cancel_send", "index": index}), _queue_row) + chip.add_theme_font_size_override("font_size", 11) + for state in ["normal", "hover", "pressed"]: + var compact := _style(Color("#26343b"), Color("#40544f") if state == "normal" else TEAL, 1) + compact.content_margin_left = 8 + compact.content_margin_right = 8 + compact.content_margin_top = 3 + compact.content_margin_bottom = 3 + chip.add_theme_stylebox_override(state, compact) + chip.tooltip_text = "%s entfernen · gibt die Funken vollständig frei" % DataCatalog.SENDS[send_id]["display_name"] + index += 1 + _queue_scroll.visible = not team.send_queue.is_empty() + + +func _phase_changed(phase: int) -> void: + for panel: Control in _game_panels: + panel.visible = phase not in [GameState.Phase.MENU, GameState.Phase.GAME_OVER] + var fighting: bool = phase == GameState.Phase.COMBAT + _cards.visible = not fighting + _starter_button.visible = not fighting + _undo.visible = not fighting + _shop_panel.offset_top = -84 if fighting else -212 + if phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER]: + main_menu.occluder = model_inspector + main_menu.enter(phase == GameState.Phase.GAME_OVER) + else: + main_menu.leave() + if phase == GameState.Phase.BUILD: + if GameState.wave == 1: + _summary.text = "" + _queue_signature = "@" + notify("Bauphase: neue Wächter, Aufwertungen und Arbeiter sind verfügbar.") + elif phase == GameState.Phase.COMBAT: + notify("Die Formation kämpft automatisch. Deine Kämpfer kehren zur nächsten Welle zurück.") + _refresh() + + +func _show_summary(reports: Array) -> void: + var report: Dictionary = reports[0] + _summary.text = "LETZTE ABRECHNUNG\n+%d Gold: %d Grundbetrag + %d Einkommen + %d Prämien\n%d Lecks · %d Kernschaden" % [ + report.get("total_gold", 0), report.get("base_gold", 0), report.get("income", 0), + report.get("bounty", 0), report.get("leaks", 0), report.get("core_damage", 0)] + + +func notify(message: String, is_error: bool = false) -> void: + _toast.text = message + _toast.add_theme_color_override("font_color", CORAL if is_error else TEAL) + _toast_left = 6.0 + + +func toggle_pause() -> void: + if GameState.phase in [GameState.Phase.MENU, GameState.Phase.GAME_OVER]: + return + GameState.paused = not GameState.paused + if GameState.paused: + Soundscape.stop_combat() + _refresh() + + +func _toggle_speed() -> void: + GameState.speed = 2 if GameState.speed == 1 else 1 + _refresh() + + +func _emit_selected(type: String) -> void: + command_requested.emit({"type": type, "uid": selected_uid}) + + +func _upgrade_selected() -> void: + _emit_selected("upgrade") + + +func _queue_send() -> void: + command_requested.emit({"type": "queue_send", "type_id": "s%02d" % (_send_picker.selected + 1)}) + + +func _cancel_last_send() -> void: + var queue: Array = EconomyManager.get_team(0).send_queue + if not queue.is_empty(): + command_requested.emit({"type": "cancel_send", "index": queue.size() - 1}) + + +func _icon(id: String, parent: Node, minimum: Vector2) -> TextureRect: + var image := TextureRect.new() + image.texture = AssetLibrary.icon(id) + image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + image.custom_minimum_size = minimum + image.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(image) + return image + +func _refresh_type_icons(data: Dictionary) -> void: + var key: String = "%s:%s" % [data.attack_type, data.armor_type] + if _selection_types.get_meta("key", "") == key: + return + _selection_types.set_meta("key", key) + for child: Node in _selection_types.get_children(): + child.free() + _icon(["type_damage_blade","type_damage_pierce","type_damage_pulse"][int(data.attack_type)], _selection_types, Vector2(25,25)) + _label(DataCatalog.DAMAGE_NAMES[data.attack_type],12,_selection_types,GOLD) + _icon(["type_armor_light","type_armor_heavy","type_armor_aether"][int(data.armor_type)], _selection_types, Vector2(25,25)) + _label(DataCatalog.ARMOR_NAMES[data.armor_type],12,_selection_types,MUTED) + + +func _make_settings() -> void: + settings_panel = ColorRect.new() + settings_panel.color = Color(.02, .03, .04, .9) + settings_panel.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + # Reached from the title menu as well as in play: it shares the menu theme. + settings_panel.theme = SaumwachtTheme.shared() + add_child(settings_panel) + var center := CenterContainer.new() + center.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + settings_panel.add_child(center) + var panel := PanelContainer.new() + panel.theme_type_variation = "MenuPanel" + panel.custom_minimum_size.x = 760 + center.add_child(panel) + var column := VBoxContainer.new() + column.add_theme_constant_override("separation", 12) + panel.add_child(column) + var heading := _themed_label("Optionen & Steuerung", "HeadingLabel", column) + heading.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _themed_label("Eine laufende Partie pausiert, solange dieses Fenster geöffnet ist.", "MutedLabel", column).horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _themed_label("LAUTSTÄRKE", "SectionLabel", column) + _volume_slider = HSlider.new() + _volume_slider.max_value = 100 + _volume_slider.step = 1 + _volume_slider.custom_minimum_size.y = 28 + column.add_child(_volume_slider) + _volume_slider.value_changed.connect(func(value: float): + Preferences.volume = value / 100.0 + Preferences.commit()) + _volume_slider.drag_ended.connect(func(_changed: bool): Soundscape.play("place")) + var toggles := GridContainer.new() + toggles.columns = 2 + toggles.add_theme_constant_override("h_separation", 28) + toggles.add_theme_constant_override("v_separation", 4) + column.add_child(toggles) + _mute_check = CheckButton.new() + _mute_check.text = "Ton stumm [M]" + toggles.add_child(_mute_check) + _mute_check.toggled.connect(func(value: bool): + Preferences.muted = value + Preferences.commit()) + _follow_check = CheckButton.new() + _follow_check.text = "Kamera folgt dem Kampf" + toggles.add_child(_follow_check) + _follow_check.toggled.connect(func(value: bool): + Preferences.follow_camera = value + Preferences.commit()) + _fullscreen_check = CheckButton.new() + _fullscreen_check.text = "Vollbild [F11]" + toggles.add_child(_fullscreen_check) + _fullscreen_check.toggled.connect(func(value: bool): + Preferences.fullscreen = value + Preferences.commit()) + _reduced_check = CheckButton.new() + _reduced_check.text = "Bewegung reduzieren" + _reduced_check.tooltip_text = "Menü ohne Kamerafahrten, Kameraatmen, Partikel und Überblendungen." + toggles.add_child(_reduced_check) + _reduced_check.toggled.connect(func(value: bool): + Preferences.reduced_motion = value + Preferences.commit()) + column.add_child(HSeparator.new()) + _themed_label("STEUERUNG", "SectionLabel", column) + _themed_label("1–5 Wächter wählen Linksklick Bauen / Auswählen\nRechtsklick / Esc Bauauftrag abbrechen\nLeertaste Kampf / nächste Welle P Pause\nTab Front wechseln C Arbeiter & Kristall\nMausrad Zoomen Shift + Klick Mehrfach bauen\nQ / E Kamera drehen Mittlere Maustaste ziehen Verschieben\nR Kamera zurücksetzen und dem Kampf wieder folgen\nV 3D-Modelle ansehen, drehen und Bewegungen abspielen", "Label", column) + _themed_label("Startformation: Tank, Nahkämpfer und Schütze.\nFunkenleser liefern ab der nächsten Welle Funken.\nSöldner schickst du ab Welle 3 zum Rivalen.", "MutedLabel", column) + var row := HBoxContainer.new() + row.add_theme_constant_override("separation", 12) + column.add_child(row) + var back := _button("ZURÜCK [Esc]", toggle_settings, row) + back.theme_type_variation = "PrimaryButton" + back.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _button("Neue Partie", func(): + settings_panel.hide() + main_menu.pending_screen = MainMenu.Screen.SETUP + menu_requested.emit(), row).tooltip_text = "Beendet diese Partie und öffnet die Bundauswahl." + _button("Spiel beenden", func(): Soundscape.quit_game(), row) + settings_panel.visible = false + +func _themed_label(text_value: String, variation: String, parent: Node) -> Label: + var label := Label.new() + label.text = text_value + label.theme_type_variation = variation + label.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(label) + return label + +func sync_settings() -> void: + _volume_slider.set_value_no_signal(Preferences.volume * 100.0) + _mute_check.set_pressed_no_signal(Preferences.muted) + _follow_check.set_pressed_no_signal(Preferences.follow_camera) + _fullscreen_check.set_pressed_no_signal(Preferences.fullscreen) + _reduced_check.set_pressed_no_signal(Preferences.reduced_motion) + +func toggle_settings() -> void: + if settings_panel.visible: + settings_panel.hide() + GameState.paused = _settings_paused + if is_instance_valid(_settings_focus) and _settings_focus.is_visible_in_tree(): + _settings_focus.grab_focus() + else: + _settings_focus = get_viewport().gui_get_focus_owner() + _settings_paused = GameState.paused + GameState.paused = true + Soundscape.stop_combat() + sync_settings() + settings_panel.show() + _volume_slider.grab_focus() + _refresh() + +func update_battle_readout(units: Array, manual_camera: bool) -> void: + _camera_status.text = ("Freie Kamera · R Zurücksetzen" if manual_camera else "Q / E Drehen · Mausrad Zoom") + " · F1 Hilfe" + var boss = null + if GameState.phase == GameState.Phase.COMBAT: + for unit in units: + if unit.alive and unit.is_attacker and unit.team_id == viewed_team and unit._is_boss(): + boss = unit + break + _boss_bar.visible = boss != null + _boss_label.visible = boss != null + if boss != null: + _boss_bar.max_value = boss.max_hp + _boss_bar.value = boss.hp + _boss_label.text = "%s · %d / %d HP" % [boss.data.display_name, ceili(boss.hp), ceili(boss.max_hp)] + +func inspect_selected_model() -> void: + var id: String = build_type + for entry: Dictionary in EconomyManager.get_team(0).roster: + if entry.uid == selected_uid: + id = str(entry.type_id) + break + if id.is_empty(): + id = "w10" if GameState.factions[0] == "wurzelbund" else "g04" + model_inspector.show_model(id) + +func request_wave_start() -> void: + if GameState.paused: + notify("Setze das Spiel mit P fort, bevor du eine Welle startest.") + return + if GameState.phase == GameState.Phase.BUILD and EconomyManager.get_team(0).roster.is_empty(): + notify("Setze zuerst Wächter oder nutze die Startformation.", true) + return + ready_requested.emit() diff --git a/scripts/ui/hud.gd.uid b/scripts/ui/hud.gd.uid new file mode 100644 index 0000000..dc7ce58 --- /dev/null +++ b/scripts/ui/hud.gd.uid @@ -0,0 +1 @@ +uid://bjqfrhvaalqmx diff --git a/scripts/ui/main_menu.gd b/scripts/ui/main_menu.gd new file mode 100644 index 0000000..36945c7 --- /dev/null +++ b/scripts/ui/main_menu.gd @@ -0,0 +1,518 @@ +class_name MainMenu +extends Control +## Title screen and match setup in front of the menu diorama. +## Presentation state (screen, camera shot, fades) lives here only. Match options are +## written through GameState exactly as before; nothing from the stage reaches a match. + +signal start_requested +signal settings_requested +signal models_requested +signal quit_requested +signal selection_changed + +const Stage = preload("res://scripts/presentation/menu_stage.gd") +const FADE := .22 +enum Screen { TITLE, SETUP } + +var screen: int = Screen.TITLE +var pending_screen: int = Screen.TITLE +var stage: Node3D +var stage_view: SubViewport +var occluder: Control +var start_button: Button +var new_game_button: Button +var faction_choice: FactionChoice +var rival_choice: ChoiceGroup +var mode_choice: ChoiceGroup +var ai_choice: ChoiceGroup +var timed_toggle: CheckButton +var length_summary: Label +var result_title: Label +var result_body: Label +var reduced_motion: bool = false +var _stage_rect: TextureRect +var _title_screen: Control +var _setup_screen: Control +var _title_scrim: TextureRect +var _setup_scrim: TextureRect +var _shield: Control +var _shield_left: float = 0.0 +var _fade: Tween +var _locked: bool = false +var _active: bool = false +var _leaving: bool = false +var _result_panel: Control +var _change_button: Button +var _models_button: Button +var _options_button: Button +var _advanced: VBoxContainer +var _advanced_button: Button +var _advanced_summary: Label +var _timed_hint: Label +var _title_caption: Label +var _style_heading: Label +var _style_facts: Label +var _setup_caption: Label + +func _ready() -> void: + name = "MainMenu" + theme = SaumwachtTheme.shared() + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + mouse_filter = Control.MOUSE_FILTER_STOP + _build_stage() + _title_scrim = _scrim(Vector2(0, 1), Vector2(.78, .18), [.92, .62, 0.0], [0.0, .42, 1.0]) + _setup_scrim = _scrim(Vector2(0, .5), Vector2(1, .5), [.9, .62, 0.0], [0.0, .36, .6]) + var top := _scrim(Vector2(.5, 0), Vector2(.5, 1), [.55, 0.0, 0.0], [0.0, .2, 1.0]) + top.name = "TopVignette" + _build_title() + _build_setup() + _shield = Control.new() + _shield.name = "InputShield" + _shield.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _shield.mouse_filter = Control.MOUSE_FILTER_STOP + _shield.visible = false + add_child(_shield) + get_tree().root.size_changed.connect(_resize_stage) + _resize_stage() + Preferences.changed.connect(_apply_preferences) + _apply_preferences() + sync() + +# ---------------------------------------------------------------- building +func _build_stage() -> void: + stage_view = SubViewport.new() + stage_view.name = "StageViewport" + stage_view.own_world_3d = true + stage_view.msaa_3d = Viewport.MSAA_2X + stage_view.render_target_update_mode = SubViewport.UPDATE_DISABLED + add_child(stage_view) + stage = Stage.new() + stage_view.add_child(stage) + _stage_rect = TextureRect.new() + _stage_rect.name = "StageImage" + _stage_rect.texture = stage_view.get_texture() + _stage_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _stage_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + _stage_rect.stretch_mode = TextureRect.STRETCH_SCALE + _stage_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(_stage_rect) + +func _scrim(from: Vector2, to: Vector2, alphas: Array, offsets: Array) -> TextureRect: + var gradient := Gradient.new() + gradient.offsets = PackedFloat32Array(offsets) + var colors := PackedColorArray() + for alpha: float in alphas: + colors.append(Color(SaumwachtTheme.NIGHT, alpha)) + gradient.colors = colors + var texture := GradientTexture2D.new() + texture.gradient = gradient + texture.fill_from = from + texture.fill_to = to + texture.width = 256 + texture.height = 256 + var rect := TextureRect.new() + rect.texture = texture + rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + rect.stretch_mode = TextureRect.STRETCH_SCALE + rect.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(rect) + return rect + +func _label(text_value: String, variation: String, parent: Node) -> Label: + var label := Label.new() + label.text = text_value + label.theme_type_variation = variation + label.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(label) + return label + +func _button(text_value: String, variation: String, parent: Node, action: Callable) -> Button: + var button := Button.new() + button.text = text_value + button.theme_type_variation = variation + button.focus_mode = Control.FOCUS_ALL + button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + button.pressed.connect(action) + parent.add_child(button) + return button + +func _emblem(path: String, size: float, parent: Node) -> TextureRect: + var image := TextureRect.new() + image.texture = load(path) + image.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + image.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + image.custom_minimum_size = Vector2(size, size) + image.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(image) + return image + +func _build_title() -> void: + _title_screen = Control.new() + _title_screen.name = "TitleScreen" + _title_screen.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _title_screen.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(_title_screen) + var column := VBoxContainer.new() + column.name = "TitleColumn" + column.anchor_top = 1.0 + column.anchor_bottom = 1.0 + column.offset_left = 88 + column.offset_right = 760 + column.offset_bottom = -72 + column.grow_vertical = Control.GROW_DIRECTION_BEGIN + column.add_theme_constant_override("separation", 10) + _title_screen.add_child(column) + _result_panel = PanelContainer.new() + _result_panel.theme_type_variation = "CaptionPanel" + _result_panel.visible = false + column.add_child(_result_panel) + var result := VBoxContainer.new() + result.add_theme_constant_override("separation", 2) + _result_panel.add_child(result) + result_title = _label("", "HeadingLabel", result) + result_body = _label("", "MutedLabel", result) + var spacer := Control.new() + spacer.custom_minimum_size.y = 12 + column.add_child(spacer) + var brand := HBoxContainer.new() + brand.add_theme_constant_override("separation", 22) + column.add_child(brand) + _emblem("res://assets/ui/emblems/saumwacht.svg", 112, brand) + var names := VBoxContainer.new() + names.alignment = BoxContainer.ALIGNMENT_CENTER + names.add_theme_constant_override("separation", 0) + brand.add_child(names) + _label("SAUMWACHT", "TitleLabel", names) + _label("DIE GRÜNE KLUFT", "SubtitleLabel", names) + var lore := _label("Stelle deine Wächter auf, schütze den Saumkern und überstehe den Rivalen.", "LoreLabel", column) + lore.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + lore.custom_minimum_size.x = 560 + var gap := Control.new() + gap.custom_minimum_size.y = 22 + column.add_child(gap) + var primary_row := HBoxContainer.new() + primary_row.add_theme_constant_override("separation", 14) + column.add_child(primary_row) + new_game_button = _button("NEUE PARTIE", "PrimaryButton", primary_row, _on_title_primary) + new_game_button.name = "NewGame" + new_game_button.custom_minimum_size = Vector2(340, 64) + _change_button = _button("Bund und Partie ändern", "Button", primary_row, func() -> void: show_screen(Screen.SETUP)) + _change_button.custom_minimum_size.y = 64 + _change_button.visible = false + var secondary := HBoxContainer.new() + secondary.add_theme_constant_override("separation", 12) + column.add_child(secondary) + _models_button = _button("Modelle ansehen · V", "Button", secondary, func() -> void: models_requested.emit()) + _options_button = _button("Optionen & Steuerung · F1", "Button", secondary, func() -> void: settings_requested.emit()) + var quit := _button("Spiel beenden", "QuietButton", column, func() -> void: quit_requested.emit()) + quit.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN + var version := _label("Demo %s · Einzelspieler" % str(ProjectSettings.get_setting("application/config/version", "")), "MutedLabel", _title_screen) + version.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT) + version.offset_left = -360 + version.offset_right = -40 + version.offset_top = 30 + version.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + _title_caption = _caption(_title_screen, "Glutpakt und Wurzelbund an den Ufern der Grünen Kluft") + +func _caption(parent: Control, text_value: String) -> Label: + var plate := PanelContainer.new() + plate.theme_type_variation = "CaptionPanel" + plate.anchor_left = 1.0 + plate.anchor_right = 1.0 + plate.anchor_top = 1.0 + plate.anchor_bottom = 1.0 + plate.offset_right = -40 + plate.offset_bottom = -36 + plate.grow_horizontal = Control.GROW_DIRECTION_BEGIN + plate.grow_vertical = Control.GROW_DIRECTION_BEGIN + plate.mouse_filter = Control.MOUSE_FILTER_IGNORE + parent.add_child(plate) + var label := _label(text_value, "MutedLabel", plate) + label.add_theme_font_size_override("font_size", 15) + return label + +func _build_setup() -> void: + _setup_screen = Control.new() + _setup_screen.name = "SetupScreen" + _setup_screen.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _setup_screen.mouse_filter = Control.MOUSE_FILTER_IGNORE + _setup_screen.visible = false + add_child(_setup_screen) + var panel := PanelContainer.new() + panel.name = "SetupPanel" + panel.theme_type_variation = "MenuPanel" + panel.anchor_bottom = 1.0 + panel.offset_left = 40 + panel.offset_top = 30 + panel.offset_right = 700 + panel.offset_bottom = -30 + _setup_screen.add_child(panel) + var layout := VBoxContainer.new() + layout.add_theme_constant_override("separation", 12) + panel.add_child(layout) + var top := HBoxContainer.new() + layout.add_child(top) + var back := _button("‹ Hauptmenü Esc", "QuietButton", top, func() -> void: show_screen(Screen.TITLE)) + back.name = "Back" + var eyebrow := _label("NEUE PARTIE", "EyebrowLabel", top) + eyebrow.size_flags_horizontal = Control.SIZE_EXPAND_FILL + eyebrow.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + _label("Wähle deinen Bund", "HeadingLabel", layout) + var scroll := ScrollContainer.new() + scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED + scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL + layout.add_child(scroll) + # Inner padding keeps focus rings inside the scroll clip. + var padding := MarginContainer.new() + padding.size_flags_horizontal = Control.SIZE_EXPAND_FILL + for side: String in ["left", "right", "top", "bottom"]: + padding.add_theme_constant_override("margin_" + side, 8) + scroll.add_child(padding) + var body := VBoxContainer.new() + body.size_flags_horizontal = Control.SIZE_EXPAND_FILL + body.add_theme_constant_override("separation", 12) + padding.add_child(body) + faction_choice = FactionChoice.new() + faction_choice.name = "FactionChoice" + body.add_child(faction_choice) + faction_choice.item_selected.connect(func(index: int) -> void: + if GameState.select_faction(0, DataCatalog.FACTIONS[index]): + selection_changed.emit() + sync()) + # One shared play-style description for the selected Bund, next to one shared 3D preview. + _style_heading = _label("", "SectionLabel", body) + _style_facts = _label("", "CardFactLabel", body) + _style_facts.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + _style_facts.add_theme_constant_override("line_spacing", 4) + _label("PARTIELÄNGE", "SectionLabel", body) + mode_choice = ChoiceGroup.new(true) + mode_choice.name = "ModeChoice" + mode_choice.add_option("Expedition", "20 Wellen · 4 Bosse") + mode_choice.add_option("Kurzpartie", "8 Wellen · 2 Bosse") + body.add_child(mode_choice) + mode_choice.item_selected.connect(func(index: int) -> void: + GameState.select_mode(GameState.MODE_EXPEDITION if index == 0 else GameState.MODE_SHORT) + sync()) + length_summary = _label("", "MutedLabel", body) + var disclosure := HBoxContainer.new() + body.add_child(disclosure) + _advanced_button = _button("+ Weitere Einstellungen", "QuietButton", disclosure, _toggle_advanced) + _advanced_button.name = "AdvancedToggle" + _advanced_summary = _label("", "MutedLabel", disclosure) + _advanced_summary.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _advanced_summary.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT + _advanced_summary.add_theme_font_size_override("font_size", 15) + _advanced = VBoxContainer.new() + _advanced.name = "AdvancedOptions" + _advanced.add_theme_constant_override("separation", 8) + _advanced.visible = false + body.add_child(_advanced) + _label("RIVALENBUND", "SectionLabel", _advanced) + rival_choice = ChoiceGroup.new(true) + rival_choice.name = "RivalChoice" + for id: String in DataCatalog.FACTIONS: + rival_choice.add_option(DataCatalog.FACTION_NAMES[id]) + _advanced.add_child(rival_choice) + rival_choice.item_selected.connect(func(index: int) -> void: + GameState.select_faction(1, DataCatalog.FACTIONS[index]) + sync()) + _label("KI-STUFE", "SectionLabel", _advanced) + ai_choice = ChoiceGroup.new(true) + ai_choice.name = "AiChoice" + ai_choice.add_option("Lernmodus", "feste Formationen, milde Söldnerangriffe") + ai_choice.add_option("Standard", "verbessert sich nach Lecks, volle Söldnerangriffe") + _advanced.add_child(ai_choice) + ai_choice.item_selected.connect(func(index: int) -> void: + GameState.ai_level = index + sync()) + timed_toggle = CheckButton.new() + timed_toggle.name = "TimedBuild" + timed_toggle.text = "Bauzeit begrenzen (45 / 30 Sekunden)" + timed_toggle.focus_mode = Control.FOCUS_ALL + _advanced.add_child(timed_toggle) + timed_toggle.toggled.connect(func(value: bool) -> void: + GameState.timed_build = value + sync()) + start_button = _button("PARTIE BEGINNEN ›", "PrimaryButton", layout, _on_start) + start_button.name = "StartMatch" + start_button.custom_minimum_size.y = 64 + _timed_hint = _label("", "MutedLabel", layout) + _timed_hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _timed_hint.add_theme_font_size_override("font_size", 15) + _setup_caption = _caption(_setup_screen, "") + +# ---------------------------------------------------------------- state +func sync() -> void: + if faction_choice == null: + return + faction_choice.select(DataCatalog.FACTIONS.find(GameState.factions[0])) + rival_choice.select(DataCatalog.FACTIONS.find(GameState.factions[1])) + var full: bool = GameState.match_mode == GameState.MODE_EXPEDITION + mode_choice.select(0 if full else 1) + ai_choice.select(clampi(GameState.ai_level, 0, 1)) + timed_toggle.set_pressed_no_signal(GameState.timed_build) + length_summary.text = "Zwanzig Wellen · vier Bosse · etwa 20 bis 30 Minuten" if full else "Acht Wellen · zwei Bosse · etwa 7 bis 10 Minuten" + _advanced_summary.text = "Rivale %s · %s · Bauzeit %s" % [DataCatalog.FACTION_NAMES[GameState.factions[1]], + "Lernmodus" if GameState.ai_level == GameState.AI_LEARNING else "Standard", "begrenzt" if GameState.timed_build else "frei"] + _timed_hint.text = "Bauphasen enden nach 45, danach je 30 Sekunden; der Kampf startet dann selbst." if GameState.timed_build else "Du startest jede Welle selbst mit der Leertaste." + var own: String = GameState.factions[0] + _style_heading.text = "SPIELWEISE · " + DataCatalog.FACTION_NAMES[own].to_upper() + var lines: PackedStringArray = [] + for fact: String in FactionChoice.PROFILES[own].facts: + lines.append("• " + fact) + lines.append("• Startformation mit Tank, Nahkämpfer und Schütze für %d Gold" % FactionChoice.starter_cost(own)) + _style_facts.text = "\n".join(lines) + var names: PackedStringArray = [] + for entry: Array in Stage.SETUPS[GameState.factions[0]].figures: + names.append(str(DataCatalog.get_unit(entry[0]).display_name)) + names.append("Saumkern") + _setup_caption.text = "IM BILD " + " · ".join(names) + if screen == Screen.SETUP and _active and stage.current_shot() != GameState.factions[0]: + stage.set_shot_named(GameState.factions[0], reduced_motion) + +func is_transitioning() -> bool: + return _shield.visible + +func _toggle_advanced() -> void: + _advanced.visible = not _advanced.visible + if _advanced.visible: + var scroll: ScrollContainer = _advanced.get_parent().get_parent().get_parent() + scroll.ensure_control_visible.call_deferred(_advanced) + _advanced_button.text = ("– Weniger Einstellungen" if _advanced.visible else "+ Weitere Einstellungen") + _advanced_summary.visible = not _advanced.visible + +func _apply_preferences() -> void: + reduced_motion = Preferences.reduced_motion + stage.set_reduced_motion(reduced_motion) + +func _resize_stage() -> void: + var pixels: Vector2i = get_tree().root.size + if pixels.x < 16 or pixels.y < 16: + pixels = Vector2i(get_viewport_rect().size) + stage_view.size = pixels + +func _set_stage_active(on: bool) -> void: + _active = on + stage.process_mode = Node.PROCESS_MODE_INHERIT if on else Node.PROCESS_MODE_DISABLED + stage_view.render_target_update_mode = SubViewport.UPDATE_ALWAYS if on else SubViewport.UPDATE_DISABLED + # The arena is hidden behind the opaque stage image; skip rendering it meanwhile. + get_tree().root.disable_3d = on + +func _process(delta: float) -> void: + if _shield_left > 0.0: + _shield_left -= delta + if _shield_left <= 0.0 and not _leaving: + _shield.visible = false + if _active: + var covered: bool = is_instance_valid(occluder) and occluder.visible + stage_view.render_target_update_mode = SubViewport.UPDATE_DISABLED if covered else SubViewport.UPDATE_ALWAYS + +func _guard(seconds: float) -> void: + _shield.visible = true + _shield_left = maxf(_shield_left, seconds) + +func _input(event: InputEvent) -> void: + # While a screen fades, clicks and confirm keys must not reach half-hidden controls. + if visible and _shield.visible and (event is InputEventMouseButton or event.is_action("ui_accept")): + get_viewport().set_input_as_handled() + +func _unhandled_input(event: InputEvent) -> void: + if not visible or _shield.visible or not event.is_action_pressed("ui_cancel"): + return + if screen == Screen.SETUP: + show_screen(Screen.TITLE) + get_viewport().set_input_as_handled() + +# ---------------------------------------------------------------- flow +func enter(game_over: bool = false) -> void: + if _fade != null: + _fade.kill() + _leaving = false + _locked = false + visible = true + modulate.a = 1.0 + _set_stage_active(true) + _result_panel.visible = game_over + _change_button.visible = game_over + new_game_button.text = "NOCHMAL SPIELEN" if game_over else "NEUE PARTIE" + if game_over: + result_title.text = ["SIEG AM SAUM", "NIEDERLAGE AM SAUM"][GameState.outcome] if GameState.outcome >= 0 else "GLEICHSTAND AM SAUM" + result_body.text = "Welle %d von %d · Dein Kern %d HP · Rivalenkern %d HP" % [GameState.wave, DataCatalog.wave_count(), GameState.core_hp[0], GameState.core_hp[1]] + var target: int = Screen.TITLE if game_over else pending_screen + pending_screen = Screen.TITLE + screen = -1 + sync() + show_screen(target, true) + +func leave() -> void: + if not visible or _leaving: + return + _leaving = true + get_tree().root.disable_3d = false + if reduced_motion or DisplayServer.get_name() == "headless": + _finish_leave() + return + _guard(FADE + .1) + _fade = create_tween() + _fade.tween_property(self, "modulate:a", 0.0, FADE) + _fade.tween_callback(_finish_leave) + +func _finish_leave() -> void: + visible = false + _shield.visible = false + _shield_left = 0.0 + _leaving = false + modulate.a = 1.0 + _set_stage_active(false) + +func show_screen(next: int, instant: bool = false) -> void: + var from: Control = _title_screen if screen == Screen.TITLE else (_setup_screen if screen == Screen.SETUP else null) + var to: Control = _title_screen if next == Screen.TITLE else _setup_screen + screen = next + stage.set_shot_named("title" if next == Screen.TITLE else GameState.factions[0], instant or reduced_motion) + _title_scrim.visible = next == Screen.TITLE + _setup_scrim.visible = next == Screen.SETUP + if _fade != null and _fade.is_valid(): + _fade.kill() + for node: Control in [_title_screen, _setup_screen]: + if node != to and node != from: + node.visible = false + if instant or reduced_motion or from == null or from == to: + if from != null and from != to: + from.visible = false + to.visible = true + to.modulate.a = 1.0 + _focus_default.call_deferred() + return + _guard(FADE + .05) + to.visible = true + to.modulate.a = 0.0 + _fade = create_tween() + _fade.tween_property(from, "modulate:a", 0.0, FADE * .6) + _fade.parallel().tween_property(to, "modulate:a", 1.0, FADE).set_delay(FADE * .25) + _fade.tween_callback(func() -> void: + from.visible = false + from.modulate.a = 1.0) + _focus_default.call_deferred() + +func _focus_default() -> void: + if not is_visible_in_tree(): + return + if screen == Screen.SETUP: + faction_choice.focus_selected() + else: + new_game_button.grab_focus() + +func _on_title_primary() -> void: + if GameState.phase == GameState.Phase.GAME_OVER: + _on_start() + else: + show_screen(Screen.SETUP) + +func _on_start() -> void: + # One start per menu visit; a second click during the fade lands on the shield. + if _locked: + return + _locked = true + start_requested.emit() diff --git a/scripts/ui/main_menu.gd.uid b/scripts/ui/main_menu.gd.uid new file mode 100644 index 0000000..c54ff80 --- /dev/null +++ b/scripts/ui/main_menu.gd.uid @@ -0,0 +1 @@ +uid://bwpvi6msb72yy diff --git a/scripts/ui/model_inspector.gd b/scripts/ui/model_inspector.gd new file mode 100644 index 0000000..4123b76 --- /dev/null +++ b/scripts/ui/model_inspector.gd @@ -0,0 +1,264 @@ +extends ColorRect +## In-game close-up of the actual animated model; the match pauses underneath. +signal closed +var _previous_pause: bool = false +var _view: SubViewport +var _root: Node3D +var _turntable: Node3D +var _figure: Node3D +var _camera: Camera3D +var _time: float = 0 +var _walking: bool = false +var _attacking: bool = false +var _rotate: bool = true +var _close_button: Button +var _caption: Label +var _details: Label +var _previous_focus: Control +var _selector: OptionButton +var _rotate_button: CheckButton +var model_id: String = "" +var _legacy_buttons: Array[Control] = [] +var _clip_row: HBoxContainer +var _clip_selector: OptionButton +var _clip_time: float = 0.0 +var _clip_paused: bool = false +var _clip_slider: HSlider +var _clip_readout: Label +const CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Angriff links", "attack_b":"Angriff rechts", "hit":"Treffer", "ability":"Fähigkeit", "death":"Tod"} +const WORKER_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Tragen", "stop":"Anhalten", "strike":"Werkzeugkontakt", "pickup":"Aufnehmen", "deposit":"Einfüllen", "return":"Rückkehr", "hit":"Treffer", "death":"Tod"} +const RINGBORKE_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Schildstoß links", "attack_b":"Hieb rechts", "hit":"Treffer", "ability":"Heilung", "death":"Tod"} +const BASALT_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Schlag links", "attack_b":"Schlag rechts", "hit":"Treffer", "ability":"Schutzhaltung", "death":"Tod"} +const QUELL_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Ranke links", "attack_b":"Ranke rechts", "hit":"Treffer", "ability":"Mehrheilung", "death":"Tod"} +const FUNKEN_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Freier Schuss", "attack_b":"Angelegter Schuss", "hit":"Treffer", "ability":"Durchschlagschuss", "death":"Tod"} +const GLASS_CLIP_LABELS = {"idle":"Ruhe", "start":"Anlaufen", "walk":"Laufen", "stop":"Anhalten", "attack_a":"Freier Schuss", "attack_b":"Angelegter Schuss", "hit":"Treffer", "ability":"Panzerbrecherschuss", "death":"Tod"} + +func _ready() -> void: + color = Color(.015, .025, .04, 1) + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + var margin := MarginContainer.new() + margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + for side: String in ["left","right","top","bottom"]: + margin.add_theme_constant_override("margin_"+side,32) + add_child(margin) + var layout := VBoxContainer.new() + margin.add_child(layout) + var header := HBoxContainer.new() + layout.add_child(header) + _caption = Label.new() + _caption.add_theme_font_size_override("font_size",28) + _caption.size_flags_horizontal = Control.SIZE_EXPAND_FILL + header.add_child(_caption) + _selector = OptionButton.new() + for id: String in DataCatalog.UNITS: + _selector.add_item(str(DataCatalog.UNITS[id].display_name)) + _selector.set_item_metadata(_selector.item_count-1,id) + _selector.add_item("Funkenleser") + _selector.set_item_metadata(_selector.item_count-1,"worker") + _selector.item_selected.connect(func(index: int): _select_model(str(_selector.get_item_metadata(index)))) + header.add_child(_selector) + var close := Button.new() + _close_button = close + close.text = "ZURÜCK [Esc / V]" + close.pressed.connect(hide_model) + header.add_child(close) + _details = Label.new() + layout.add_child(_details) + var container := SubViewportContainer.new() + container.stretch = true + container.size_flags_vertical = Control.SIZE_EXPAND_FILL + container.mouse_filter = Control.MOUSE_FILTER_STOP + container.gui_input.connect(_drag) + layout.add_child(container) + _view = SubViewport.new() + _view.own_world_3d = true + _view.msaa_3d = Viewport.MSAA_4X + _view.render_target_update_mode = SubViewport.UPDATE_DISABLED + container.add_child(_view) + _root = Node3D.new() + _view.add_child(_root) + var environment := WorldEnvironment.new() + environment.environment = Environment.new() + preload("res://scripts/presentation/lighting.gd").configure(environment.environment,true) + _root.add_child(environment) + for entry: Array in [[Vector3(-40,-30,0),Color("fff0dc"),1.35],[Vector3(-30,140,0),Color("bdcee8"),.42]]: + var light := DirectionalLight3D.new() + light.rotation_degrees = entry[0] + light.light_color = entry[1] + light.light_energy = entry[2] + light.shadow_enabled = entry[2] > 1.0 + light.light_angular_distance = 1.5 + _root.add_child(light) + _turntable = Node3D.new() + _root.add_child(_turntable) + var pedestal := MeshInstance3D.new() + var disc := CylinderMesh.new() + disc.top_radius = 1.12 + disc.bottom_radius = 1.16 + disc.height = .075 + disc.radial_segments = 64 + var stone := StandardMaterial3D.new() + stone.albedo_color = Color("1a2430") + stone.roughness = .55 + stone.metallic = .25 + disc.material = stone + pedestal.mesh = disc + pedestal.position.y = -.04 + _root.add_child(pedestal) + var rim := MeshInstance3D.new() + var rim_mesh := TorusMesh.new() + rim_mesh.inner_radius = 1.05 + rim_mesh.outer_radius = 1.10 + rim_mesh.rings = 48 + rim_mesh.ring_segments = 4 + var glow := StandardMaterial3D.new() + glow.albedo_color = Color("7fe8c8") + glow.emission_enabled = true + glow.emission = Color("4ec9a8") + glow.emission_energy_multiplier = 1.8 + glow.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + rim.mesh = rim_mesh + rim.material_override = glow + rim.position.y = -.005 + _root.add_child(rim) + _camera = Camera3D.new() + _camera.projection = Camera3D.PROJECTION_ORTHOGONAL + _camera.size = 2.8 + _camera.position = Vector3(3,2.0,4.8) + _root.add_child(_camera) + _camera.look_at(Vector3(0,.85,0),Vector3.UP) + var row := HBoxContainer.new() + row.alignment = BoxContainer.ALIGNMENT_CENTER + layout.add_child(row) + for title: String in ["Automatisch drehen","Gehen","Angreifen"]: + var button := CheckButton.new() + button.text = title + row.add_child(button) + if title == "Automatisch drehen": + _rotate_button = button + button.button_pressed = true + button.toggled.connect(func(value: bool): _rotate = value) + elif title == "Gehen": + _legacy_buttons.append(button) + button.toggled.connect(func(value: bool): _walking = value) + else: + _legacy_buttons.append(button) + button.toggled.connect(func(value: bool): _attacking = value) + _clip_row = HBoxContainer.new() + _clip_row.alignment = BoxContainer.ALIGNMENT_CENTER + layout.add_child(_clip_row) + _clip_selector = OptionButton.new() + for clip: String in CLIP_LABELS: + _clip_selector.add_item(CLIP_LABELS[clip]) + _clip_selector.set_item_metadata(_clip_selector.item_count-1,clip) + _clip_selector.item_selected.connect(func(_index: int): _clip_time = 0.0) + _clip_row.add_child(_clip_selector) + var pause := CheckButton.new() + pause.text = "Animation pausieren" + pause.toggled.connect(func(value: bool): _clip_paused = value) + _clip_row.add_child(pause) + var restart := Button.new() + restart.text = "Von vorn" + restart.pressed.connect(func(): _clip_time = 0.0) + _clip_row.add_child(restart) + _clip_slider = HSlider.new() + _clip_slider.custom_minimum_size.x = 180 + _clip_slider.min_value = 0 + _clip_slider.max_value = 1 + _clip_slider.step = .001 + _clip_slider.value_changed.connect(func(value: float): + if is_instance_valid(_figure) and _figure.has_method("clip_length"): + _clip_time = value*_figure.clip_length(str(_clip_selector.get_selected_metadata()))) + _clip_row.add_child(_clip_slider) + _clip_readout = Label.new() + _clip_readout.custom_minimum_size.x = 120 + _clip_row.add_child(_clip_readout) + var hint := Label.new() + hint.text = "Ziehen: drehen · Mausrad: vergrößern · Die laufende Partie ist pausiert." + hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + layout.add_child(hint) + hide() + +func show_model(id: String) -> void: + if visible or not (DataCatalog.UNITS.has(id) or id == "worker"): + return + _previous_pause = GameState.paused + _previous_focus = get_viewport().gui_get_focus_owner() + GameState.paused = true + Soundscape.stop_combat() + _select_model(id) + _view.render_target_update_mode = SubViewport.UPDATE_ALWAYS + show() + _close_button.grab_focus() + +func _select_model(id: String) -> void: + model_id = id + for index: int in range(_selector.item_count): + if _selector.get_item_metadata(index) == id: + _selector.select(index) + if is_instance_valid(_figure): + _figure.free() + _figure = AssetLibrary.instantiate_fighter(id) + _turntable.add_child(_figure) + var bounds: AABB = _figure.get_aabb() + var factor: float = 1.8/maxf(bounds.size.y,bounds.size.x*.80) + _figure.scale = Vector3.ONE*factor + _figure.position = -Vector3(bounds.get_center().x,bounds.position.y,bounds.get_center().z)*factor + _turntable.rotation.y = 0 + _camera.size = 2.8 + _time = 0 + _caption.text = "Funkenleser" if id == "worker" else str(DataCatalog.UNITS[id].display_name) + var record: Dictionary = AssetLibrary._models[id] + _details.text = "%s · %d Dreiecke · Tatsächliches Spielmodell" % [id.to_upper(),int(record.triangles)] + var skeletal: bool = record.get("skeletal",false) + _clip_row.visible = skeletal + for button: Control in _legacy_buttons: + button.visible = not skeletal + _clip_time = 0.0 + _clip_selector.clear() + var labels: Dictionary = WORKER_CLIP_LABELS if id == "worker" else (RINGBORKE_CLIP_LABELS if id == "w04" else (BASALT_CLIP_LABELS if id == "g04" else (QUELL_CLIP_LABELS if id == "w10" else (FUNKEN_CLIP_LABELS if id == "g05" else (GLASS_CLIP_LABELS if id == "g06" else CLIP_LABELS))))) + for clip: String in labels: + _clip_selector.add_item(labels[clip]) + _clip_selector.set_item_metadata(_clip_selector.item_count-1,clip) + _clip_selector.select(0) + if skeletal: + var clip_count: int = int(record.get("clips", labels.keys()).size()) if record.has("clips") else labels.size() + _details.text += " · %d Knochen · %d Bewegungen" % [int(record.bones), clip_count] + +func hide_model() -> void: + if not visible: + return + hide() + _view.render_target_update_mode = SubViewport.UPDATE_DISABLED + GameState.paused = _previous_pause + if is_instance_valid(_previous_focus): + _previous_focus.grab_focus() + closed.emit() + +func _process(delta: float) -> void: + if not visible: + return + _time += delta + if _rotate: + _turntable.rotation.y += delta*.28 + if _figure.has_method("preview"): + var clip: String = str(_clip_selector.get_selected_metadata()) + var duration: float = _figure.clip_length(clip) + if not _clip_paused: + _clip_time += delta + if _clip_time > duration + .55: + _clip_time = 0.0 + _figure.preview(clip,minf(_clip_time,duration)) + _clip_slider.set_value_no_signal(minf(_clip_time/duration,1.0)) + _clip_readout.text = "%.2f / %.2f s" % [minf(_clip_time,duration),duration] + elif _figure.has_method("pose"): + _figure.pose(_time,_walking,maxf(0,.28-fmod(_time,1.25)) if _attacking else 0.0,0,0) + +func _drag(event: InputEvent) -> void: + if event is InputEventMouseMotion and event.button_mask & MOUSE_BUTTON_MASK_LEFT: + _turntable.rotation.y += event.relative.x*.012 + if event is InputEventMouseButton and event.pressed: + if event.button_index == MOUSE_BUTTON_WHEEL_UP: + _camera.size = maxf(1.8,_camera.size-.15) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + _camera.size = minf(4.2,_camera.size+.15) diff --git a/scripts/ui/model_inspector.gd.uid b/scripts/ui/model_inspector.gd.uid new file mode 100644 index 0000000..4ecfbcd --- /dev/null +++ b/scripts/ui/model_inspector.gd.uid @@ -0,0 +1 @@ +uid://cna2bqgo2eo84 diff --git a/scripts/ui/theme/forged_style.gd b/scripts/ui/theme/forged_style.gd new file mode 100644 index 0000000..9ef3503 --- /dev/null +++ b/scripts/ui/theme/forged_style.gd @@ -0,0 +1,69 @@ +@tool +class_name ForgedStyle +extends StyleBox +## Vector-drawn plate for the Saumwacht theme: chamfered corners, a bronze edge, +## an inset line and an optional top bevel. Drawn per frame, so it stays crisp at any UI scale. + +@export var fill_top: Color = Color("1b2027") +@export var fill_bottom: Color = Color("12161b") +@export var edge: Color = Color("8a6a3c") +@export var edge_width: float = 1.5 +@export var inner: Color = Color(1, 1, 1, .05) +@export var inner_inset: float = 4.0 +@export var chamfer: float = 7.0 +@export var highlight: Color = Color(1, 1, 1, 0) +@export var shadow: Color = Color(0, 0, 0, 0) +@export var shadow_size: float = 0.0 +@export var ornaments: bool = false +@export var ornament_color: Color = Color("c99a58") +## Grows the drawing outside the control; used for focus rings that must not cover content. +@export var grow: float = 0.0 +@export var draw_fill: bool = true + +static func plate_points(rect: Rect2, cut: float) -> PackedVector2Array: + var c: float = minf(cut, minf(rect.size.x, rect.size.y) * .5) + var p: Vector2 = rect.position + var e: Vector2 = rect.end + return PackedVector2Array([Vector2(p.x + c, p.y), Vector2(e.x - c, p.y), Vector2(e.x, p.y + c), Vector2(e.x, e.y - c), + Vector2(e.x - c, e.y), Vector2(p.x + c, e.y), Vector2(p.x, e.y - c), Vector2(p.x, p.y + c)]) + +func _draw(item: RID, rect: Rect2) -> void: + var r: Rect2 = rect.grow(grow) + if r.size.x < 2.0 or r.size.y < 2.0: + return + if shadow.a > 0.0 and shadow_size > 0.0: + for layer: int in range(3): + var spread: float = shadow_size * float(layer + 1) / 3.0 + var soft := Color(shadow.r, shadow.g, shadow.b, shadow.a / 3.0) + if draw_fill: + var points := plate_points(Rect2(r.position + Vector2(0, spread * .5), r.size).grow(spread), chamfer + spread) + RenderingServer.canvas_item_add_polygon(item, points, PackedColorArray([soft])) + else: + # Rings only glow outwards; the control underneath stays untinted. + var halo := plate_points(r.grow(spread), chamfer + spread) + halo.append(halo[0]) + RenderingServer.canvas_item_add_polyline(item, halo, PackedColorArray([soft]), shadow_size / 3.0 + 1.0, true) + if draw_fill: + var points := plate_points(r, chamfer) + var colors := PackedColorArray() + for point: Vector2 in points: + colors.append(fill_top.lerp(fill_bottom, clampf((point.y - r.position.y) / r.size.y, 0.0, 1.0))) + RenderingServer.canvas_item_add_polygon(item, points, colors) + if highlight.a > 0.0: + var y: float = r.position.y + edge_width + 1.0 + RenderingServer.canvas_item_add_line(item, Vector2(r.position.x + chamfer, y), Vector2(r.end.x - chamfer, y), highlight, 1.0, true) + if inner.a > 0.0 and inner_inset > 0.0: + var inset := plate_points(r.grow(-inner_inset), maxf(1.0, chamfer - inner_inset * .45)) + inset.append(inset[0]) + RenderingServer.canvas_item_add_polyline(item, inset, PackedColorArray([inner]), 1.0, true) + if edge.a > 0.0 and edge_width > 0.0: + var outline := plate_points(r.grow(-edge_width * .5), chamfer) + outline.append(outline[0]) + RenderingServer.canvas_item_add_polyline(item, outline, PackedColorArray([edge]), edge_width, true) + if ornaments: + # Small rivet diamonds on the long edges mark forged panels without adding frames. + for x: float in [r.position.x + r.size.x * .5]: + for y: float in [r.position.y, r.end.y]: + var size: float = 3.5 + var diamond := PackedVector2Array([Vector2(x, y - size), Vector2(x + size, y), Vector2(x, y + size), Vector2(x - size, y)]) + RenderingServer.canvas_item_add_polygon(item, diamond, PackedColorArray([ornament_color])) diff --git a/scripts/ui/theme/forged_style.gd.uid b/scripts/ui/theme/forged_style.gd.uid new file mode 100644 index 0000000..8c67565 --- /dev/null +++ b/scripts/ui/theme/forged_style.gd.uid @@ -0,0 +1 @@ +uid://cs0n2yhxgyxv5 diff --git a/scripts/ui/theme/saumwacht_theme.gd b/scripts/ui/theme/saumwacht_theme.gd new file mode 100644 index 0000000..aae01fc --- /dev/null +++ b/scripts/ui/theme/saumwacht_theme.gd @@ -0,0 +1,247 @@ +class_name SaumwachtTheme +extends RefCounted +## Shared menu theme: basalt plates, bronze edges, Cinzel for titles, Alegreya for prose, +## Cantarell for controls. Components pick a look through theme_type_variation. + +const NIGHT := Color("0b0f14") +const BASALT := Color("151a20") +const BASALT_DEEP := Color("0f1317") +const PARCHMENT := Color("efe6d2") +const MUTED := Color("a9a293") +const FAINT := Color("7d7466") +const BRONZE := Color("b7874a") +const BRONZE_LIGHT := Color("e4bd7c") +const BRONZE_DEEP := Color("6b4f2e") +const FOCUS := Color("f6e2b0") +const EMBER := Color("ff9a52") +const SPRING := Color("7fe0c4") +const INK := Color("1a120a") + +const CINZEL := preload("res://assets/fonts/Cinzel-VF.ttf") +const ALEGREYA := preload("res://assets/fonts/Alegreya-VF.ttf") +const ALEGREYA_ITALIC := preload("res://assets/fonts/Alegreya-Italic-VF.ttf") +const CANTARELL := preload("res://assets/fonts/Cantarell-VF.otf") +const ForgedStyle = preload("res://scripts/ui/theme/forged_style.gd") + +static var _shared: Theme + +static func shared() -> Theme: + if _shared == null: + _shared = build() + return _shared + +static func font(base: Font, weight: float, spacing: int = 0) -> FontVariation: + var variation := FontVariation.new() + variation.base_font = base + variation.variation_opentype = {"wght": weight} + variation.spacing_glyph = spacing + return variation + +static func plate(top: Color, bottom: Color, edge: Color, edge_width: float = 1.5, cut: float = 7.0) -> StyleBox: + var style := ForgedStyle.new() + style.fill_top = top + style.fill_bottom = bottom + style.edge = edge + style.edge_width = edge_width + style.chamfer = cut + style.inner = Color(1, 1, 1, .045) + style.set_content_margin_all(12) + return style + +static func focus_ring(cut: float = 7.0) -> StyleBox: + # Keyboard focus: a bright ring outside the control plus a soft halo, distinct from hover. + var style := ForgedStyle.new() + style.draw_fill = false + style.edge = FOCUS + style.edge_width = 2.5 + style.inner = Color(FOCUS, .55) + style.inner_inset = 4.5 + style.chamfer = cut + 4.0 + style.grow = 4.0 + style.shadow = Color(FOCUS, .22) + style.shadow_size = 5.0 + return style + +static func margins(style: StyleBox, horizontal: float, vertical: float) -> StyleBox: + style.content_margin_left = horizontal + style.content_margin_right = horizontal + style.content_margin_top = vertical + style.content_margin_bottom = vertical + return style + +static func build() -> Theme: + var theme := Theme.new() + var ui := font(CANTARELL, 560.0) + theme.default_font = ui + theme.default_font_size = 17 + var display := font(CINZEL, 700.0, 2) + var display_medium := font(CINZEL, 600.0, 1) + var caps := font(CANTARELL, 700.0, 2) + var prose := font(ALEGREYA, 480.0) + var prose_italic := font(ALEGREYA_ITALIC, 460.0) + + for type: String in ["Label", "Button", "CheckButton", "OptionButton"]: + theme.set_color("font_color", type, PARCHMENT) + theme.set_color("font_shadow_color", "Label", Color(0, 0, 0, .55)) + theme.set_constant("shadow_offset_y", "Label", 1) + theme.set_constant("shadow_outline_size", "Label", 2) + _label(theme, "TitleLabel", display, 78, Color("f4e6c4")) + theme.set_color("font_outline_color", "TitleLabel", Color(0, 0, 0, .5)) + theme.set_constant("outline_size", "TitleLabel", 6) + _label(theme, "SubtitleLabel", font(CINZEL, 600.0, 7), 19, BRONZE_LIGHT) + _label(theme, "HeadingLabel", display_medium, 34, Color("f4e6c4")) + _label(theme, "SectionLabel", font(CINZEL, 700.0, 3), 16, BRONZE_LIGHT) + _label(theme, "EyebrowLabel", caps, 14, BRONZE_LIGHT) + _label(theme, "BodyLabel", prose, 20, PARCHMENT) + _label(theme, "LoreLabel", prose_italic, 21, Color("ddd3bd")) + _label(theme, "MutedLabel", ui, 16, MUTED) + _label(theme, "CardTitleLabel", display, 29, Color("f4e6c4")) + _label(theme, "CardFactLabel", ui, 17, Color("d8cfbc")) + _label(theme, "BadgeLabel", caps, 13, INK) + + # Secondary buttons are the default look; primary and quiet buttons are variations. + var secondary := margins(plate(Color("1d232b"), Color("141920"), Color("6b5a44")), 20, 11) + var secondary_hover := margins(plate(Color("27303a"), Color("1a2028"), BRONZE_LIGHT), 20, 11) + var secondary_pressed := margins(plate(Color("10141a"), Color("171c23"), BRONZE, 2.0), 20, 11) + var secondary_disabled := margins(plate(Color("15191e"), Color("111418"), Color("3a352e")), 20, 11) + _button(theme, "Button", secondary, secondary_hover, secondary_pressed, secondary_disabled, focus_ring()) + theme.set_color("font_hover_color", "Button", Color.WHITE) + theme.set_color("font_pressed_color", "Button", BRONZE_LIGHT) + theme.set_color("font_disabled_color", "Button", FAINT) + theme.set_color("font_focus_color", "Button", Color.WHITE) + + var primary := margins(plate(Color("e8c47e"), Color("b98a4a"), Color("fff0cc"), 1.5, 9.0), 30, 15) + (primary as ForgedStyle).inner = Color(INK, .35) + (primary as ForgedStyle).highlight = Color(1, 1, 1, .45) + (primary as ForgedStyle).shadow = Color(0, 0, 0, .45) + (primary as ForgedStyle).shadow_size = 8.0 + var primary_hover := margins(plate(Color("f6d898"), Color("cc9c56"), Color.WHITE, 1.5, 9.0), 30, 15) + (primary_hover as ForgedStyle).inner = Color(INK, .35) + (primary_hover as ForgedStyle).highlight = Color(1, 1, 1, .6) + (primary_hover as ForgedStyle).shadow = Color(.95, .7, .35, .35) + (primary_hover as ForgedStyle).shadow_size = 12.0 + var primary_pressed := margins(plate(Color("b98a4a"), Color("d5aa66"), Color("fff0cc"), 2.0, 9.0), 30, 15) + (primary_pressed as ForgedStyle).inner = Color(INK, .45) + var primary_disabled := margins(plate(Color("5a4c38"), Color("463a2a"), Color("7d6a4c"), 1.5, 9.0), 30, 15) + _button(theme, "PrimaryButton", primary, primary_hover, primary_pressed, primary_disabled, focus_ring(9.0)) + theme.set_type_variation("PrimaryButton", "Button") + theme.set_font("font", "PrimaryButton", display) + theme.set_font_size("font_size", "PrimaryButton", 22) + for state: String in ["font_color", "font_hover_color", "font_pressed_color", "font_focus_color", "font_hover_pressed_color"]: + theme.set_color(state, "PrimaryButton", INK) + theme.set_color("font_disabled_color", "PrimaryButton", Color("2a2218")) + + var quiet := margins(StyleBoxEmpty.new(), 10, 7) + var quiet_hover := margins(plate(Color(1, 1, 1, .05), Color(1, 1, 1, .02), Color(0, 0, 0, 0), 0.0, 5.0), 10, 7) + _button(theme, "QuietButton", quiet, quiet_hover, quiet_hover, quiet, focus_ring(5.0)) + theme.set_type_variation("QuietButton", "Button") + theme.set_color("font_color", "QuietButton", MUTED) + theme.set_color("font_hover_color", "QuietButton", PARCHMENT) + theme.set_font_size("font_size", "QuietButton", 16) + + # Segmented choices: the pressed state is the selected option (toggle mode). + var choice := margins(plate(Color("171c23"), Color("12161b"), Color("463d31")), 16, 10) + var choice_hover := margins(plate(Color("212831"), Color("171c23"), BRONZE), 16, 10) + var choice_on := margins(plate(Color("2e2a22"), Color("1d1b17"), BRONZE_LIGHT, 2.0), 16, 10) + (choice_on as ForgedStyle).inner = Color(BRONZE_LIGHT, .35) + _button(theme, "ChoiceButton", choice, choice_hover, choice_on, choice, focus_ring()) + theme.set_type_variation("ChoiceButton", "Button") + theme.set_stylebox("hover_pressed", "ChoiceButton", choice_on) + theme.set_color("font_color", "ChoiceButton", Color("cfc6b2")) + theme.set_color("font_pressed_color", "ChoiceButton", Color("fff4dc")) + theme.set_color("font_hover_pressed_color", "ChoiceButton", Color("fff4dc")) + theme.set_constant("h_separation", "ChoiceButton", 12) + theme.set_constant("icon_max_width", "ChoiceButton", 18) + + # Faction cards: a heavier plate; selected adds a double bronze frame and rivets. + var card := margins(plate(Color("1a1f26"), Color("111419"), Color("4a4034"), 1.5, 12.0), 18, 16) + var card_hover := margins(plate(Color("222932"), Color("151a20"), BRONZE, 1.5, 12.0), 18, 16) + var card_on := margins(plate(Color("2a2720"), Color("16171a"), BRONZE_LIGHT, 2.5, 12.0), 18, 16) + (card_on as ForgedStyle).inner = Color(BRONZE_LIGHT, .55) + (card_on as ForgedStyle).inner_inset = 5.0 + (card_on as ForgedStyle).ornaments = true + (card_on as ForgedStyle).ornament_color = BRONZE_LIGHT + (card_on as ForgedStyle).shadow = Color(0, 0, 0, .5) + (card_on as ForgedStyle).shadow_size = 10.0 + _button(theme, "FactionCard", card, card_hover, card_on, card, focus_ring(12.0)) + theme.set_type_variation("FactionCard", "Button") + theme.set_stylebox("hover_pressed", "FactionCard", card_on) + + var panel := margins(plate(Color(.078, .094, .114, .95), Color(.055, .066, .08, .96), Color("5c4a33"), 1.5, 12.0), 30, 26) + (panel as ForgedStyle).ornaments = true + (panel as ForgedStyle).ornament_color = Color("8a6a3c") + (panel as ForgedStyle).shadow = Color(0, 0, 0, .45) + (panel as ForgedStyle).shadow_size = 18.0 + theme.set_stylebox("panel", "MenuPanel", panel) + theme.set_type_variation("MenuPanel", "PanelContainer") + var caption := margins(plate(Color(.06, .075, .09, .82), Color(.05, .06, .075, .86), Color("4a4034"), 1.0, 6.0), 16, 9) + theme.set_stylebox("panel", "CaptionPanel", caption) + theme.set_type_variation("CaptionPanel", "PanelContainer") + var badge := margins(plate(BRONZE_LIGHT, BRONZE, Color("fff0cc"), 1.0, 4.0), 9, 3) + theme.set_stylebox("panel", "BadgePanel", badge) + theme.set_type_variation("BadgePanel", "PanelContainer") + theme.set_stylebox("panel", "PanelContainer", panel) + + var on_icon: Texture2D = load("res://assets/ui/controls/toggle_on.svg") + var off_icon: Texture2D = load("res://assets/ui/controls/toggle_off.svg") + for type: String in ["CheckButton"]: + theme.set_icon("checked", type, on_icon) + theme.set_icon("unchecked", type, off_icon) + theme.set_icon("checked_disabled", type, on_icon) + theme.set_icon("unchecked_disabled", type, off_icon) + theme.set_stylebox("normal", type, margins(StyleBoxEmpty.new(), 6, 6)) + theme.set_stylebox("hover", type, margins(plate(Color(1, 1, 1, .04), Color(1, 1, 1, .02), Color(0, 0, 0, 0), 0.0, 5.0), 6, 6)) + theme.set_stylebox("pressed", type, margins(StyleBoxEmpty.new(), 6, 6)) + theme.set_stylebox("hover_pressed", type, margins(plate(Color(1, 1, 1, .04), Color(1, 1, 1, .02), Color(0, 0, 0, 0), 0.0, 5.0), 6, 6)) + theme.set_stylebox("focus", type, focus_ring(5.0)) + theme.set_color("font_hover_color", type, Color.WHITE) + theme.set_color("font_pressed_color", type, PARCHMENT) + theme.set_color("font_hover_pressed_color", type, Color.WHITE) + theme.set_color("font_focus_color", type, Color.WHITE) + theme.set_constant("h_separation", type, 14) + + var track := StyleBoxFlat.new() + track.bg_color = Color("0c0f13") + track.border_color = Color("5c4a33") + track.set_border_width_all(1) + track.content_margin_top = 3 + track.content_margin_bottom = 3 + theme.set_stylebox("slider", "HSlider", track) + var fill := StyleBoxFlat.new() + fill.bg_color = BRONZE + fill.content_margin_top = 3 + fill.content_margin_bottom = 3 + theme.set_stylebox("grabber_area", "HSlider", fill) + theme.set_stylebox("grabber_area_highlight", "HSlider", fill) + theme.set_icon("grabber", "HSlider", load("res://assets/ui/controls/choice_on.svg")) + theme.set_icon("grabber_highlight", "HSlider", load("res://assets/ui/controls/choice_on.svg")) + theme.set_stylebox("focus", "HSlider", focus_ring(4.0)) + var rule := StyleBoxLine.new() + rule.color = Color("3a3226") + rule.thickness = 1 + theme.set_stylebox("separator", "HSeparator", rule) + theme.set_constant("separation", "HSeparator", 14) + var scroll := StyleBoxFlat.new() + scroll.bg_color = Color(1, 1, 1, .03) + var grab := StyleBoxFlat.new() + grab.bg_color = Color("5c4a33") + for key: String in ["grabber", "grabber_highlight", "grabber_pressed"]: + theme.set_stylebox(key, "VScrollBar", grab) + theme.set_stylebox("scroll", "VScrollBar", scroll) + var tooltip := margins(plate(Color("1d232b"), Color("141920"), BRONZE), 12, 8) + theme.set_stylebox("panel", "TooltipPanel", tooltip) + theme.set_color("font_color", "TooltipLabel", PARCHMENT) + return theme + +static func _label(theme: Theme, type: String, face: Font, size: int, color: Color) -> void: + theme.set_type_variation(type, "Label") + theme.set_font("font", type, face) + theme.set_font_size("font_size", type, size) + theme.set_color("font_color", type, color) + +static func _button(theme: Theme, type: String, normal: StyleBox, hover: StyleBox, pressed: StyleBox, disabled: StyleBox, focus: StyleBox) -> void: + theme.set_stylebox("normal", type, normal) + theme.set_stylebox("hover", type, hover) + theme.set_stylebox("pressed", type, pressed) + theme.set_stylebox("disabled", type, disabled) + theme.set_stylebox("focus", type, focus) diff --git a/scripts/ui/theme/saumwacht_theme.gd.uid b/scripts/ui/theme/saumwacht_theme.gd.uid new file mode 100644 index 0000000..839c1eb --- /dev/null +++ b/scripts/ui/theme/saumwacht_theme.gd.uid @@ -0,0 +1 @@ +uid://b0j22t3k2pmbw diff --git a/tests/test_runner.gd b/tests/test_runner.gd new file mode 100644 index 0000000..1a7139d --- /dev/null +++ b/tests/test_runner.gd @@ -0,0 +1,533 @@ +extends Node +## Integration checks: run as a scene so the production autoloads are available. +## godot --headless --path saumwacht-godot res://tests/test_runner.tscn + +const BattleScript = preload("res://scripts/combat/battle_controller.gd") +const UnitScript = preload("res://scripts/combat/unit.gd") +const AIScript = preload("res://scripts/ai/simple_ai.gd") + +var checks: int = 0 +var failures: Array[String] = [] + + +func _ready() -> void: + WaveManager.set_physics_process(false) + call_deferred("_run") + + +func _run() -> void: + GameState.reset_match() + GameState.factions = ["glutpakt", "glutpakt"] + GameState.timed_build = true + GameState.select_mode(GameState.MODE_SHORT) + _test_workers_and_production() + _test_formation_accounting() + _test_send_commit_and_settlement() + _test_ai_learning_level() + _test_ai_standard_level() + _test_worker_limit_and_last_wave() + _test_damage_matrix() + _test_dot_tick_and_refresh() + _test_shield_replacement() + _test_fourth_hit_bonus() + _test_splash_limit_and_lane_isolation() + _test_identity_and_formation_reset() + _test_leaks_and_timeout() + _test_core_resolution() + _test_slice_lifecycle() + if failures.is_empty(): + print("PASS: %d checks across economy, combat and the full match lifecycle." % checks) + else: + for failure: String in failures: + printerr("FAIL: " + failure) + printerr("%d / %d checks failed." % [failures.size(), checks]) + get_tree().quit(0 if failures.is_empty() else 1) + + +func _check(condition: bool, message: String) -> void: + checks += 1 + if not condition: + failures.append(message) + + +func _command(command: Dictionary, expected: bool = true) -> Dictionary: + var result: Dictionary = EconomyManager.apply_command(0, command) + _check(bool(result.get("ok", false)) == expected, + "Command %s expected ok=%s; received %s" % [command, expected, result]) + return result + + +func _open_economy_to_wave(last_wave: int) -> void: + GameState.reset_match() + EconomyManager.reset_match() + for number: int in range(1, last_wave + 1): + GameState.wave = number + GameState.set_phase(GameState.Phase.BUILD) + EconomyManager.open_build(number) + if number < last_wave: + EconomyManager.freeze(number) + EconomyManager.settle(0, number, 0) + EconomyManager.settle(1, number, 0) + + +func _test_workers_and_production() -> void: + _open_economy_to_wave(1) + var initial: Dictionary = EconomyManager.get_team(0) + _check(initial.gold == 220 and initial.sparks == 10 and initial.income == 20, + "Starting economy includes exactly one initial worker production.") + _check(initial.workers == 1 and initial.pending_workers == 0, "One worker starts active.") + EconomyManager.open_build(1) + _check(EconomyManager.get_team(0).sparks == 10, "Reopening the same build phase cannot produce twice.") + _command({"type": "worker"}) + var first: Dictionary = EconomyManager.get_team(0) + _check(first.gold == 150 and first.workers == 1 and first.pending_workers == 1, + "First worker costs 70 and activates in the next build phase.") + _check(first.sparks == 10, "A new worker cannot produce in its purchase phase.") + _command({"type": "worker"}) + _check(EconomyManager.get_team(0).gold == 60 and EconomyManager.get_team(0).pending_workers == 2, + "A second purchase immediately uses the 90 gold price tier.") + _command({"type": "worker"}, false) + _command({"type": "undo"}) + _check(EconomyManager.get_team(0) == first, "Undo restores the whole worker purchase state.") + EconomyManager.freeze(1) + EconomyManager.settle(0, 1, 0) + GameState.wave = 2 + GameState.set_phase(GameState.Phase.BUILD) + EconomyManager.open_build(2) + var next: Dictionary = EconomyManager.get_team(0) + _check(next.workers == 2 and next.pending_workers == 0 and next.sparks == 30, + "Pending worker activates once and both workers produce in wave 2.") + _command({"type": "undo"}, false) + _command({"type": "queue_send", "type_id": "s01"}, false) + + +func _test_formation_accounting() -> void: + _open_economy_to_wave(1) + _command({"type": "build", "type_id": "g02", "cell": Vector2i(0, 0)}, false) + _command({"type": "build", "type_id": "g01", "cell": Vector2i(-1, 0)}, false) + _command({"type": "build", "type_id": "g01", "cell": Vector2i(6, 0)}, false) + _command({"type": "build", "type_id": "g01", "cell": Vector2i(0, 8)}, false) + _command({"type": "build", "type_id": "g01", "cell": Vector2i(0, 0)}) + var bought: Dictionary = EconomyManager.get_team(0) + var uid: int = int(bought.roster[0].uid) + _check(bought.gold == 175 and bought.roster.size() == 1 and bought.roster[0].invested == 45, + "Buying records the unit's actual investment and debits gold.") + _command({"type": "build", "type_id": "g03", "cell": Vector2i(0, 0)}, false) + _check(EconomyManager.get_team(0) == bought, "An occupied-cell rejection has no economic side effects.") + var snapshot: Dictionary = EconomyManager.get_team(0) + snapshot.roster[0].invested = 999999 + snapshot.gold = -1 + _check(EconomyManager.get_team(0) == bought, "External snapshots cannot mutate the authoritative economy.") + _command({"type": "upgrade", "uid": uid}) + var upgraded: Dictionary = EconomyManager.get_team(0) + _check(upgraded.gold == 85 and upgraded.roster[0].type_id == "g02" + and upgraded.roster[0].invested == 135 and upgraded.roster[0].uid == uid, + "Upgrade replaces in place, preserves identity and adds only the extra price.") + _command({"type": "sell", "uid": uid}) + _check(EconomyManager.get_team(0).gold == 186 and EconomyManager.get_team(0).roster.is_empty(), + "Selling refunds floor(135 * 0.75) = 101 gold and frees the cell.") + _command({"type": "undo"}) + _check(EconomyManager.get_team(0) == upgraded, "Undo sale restores upgraded unit and gold.") + _command({"type": "undo"}) + _check(EconomyManager.get_team(0) == bought, "Undo upgrade restores the original investment.") + _command({"type": "move", "uid": uid, "cell": Vector2i(5, 7)}) + _check(EconomyManager.get_team(0).gold == 175 and EconomyManager.get_team(0).roster[0].cell == Vector2i(5, 7), + "Moving is free and accepts the last valid grid cell.") + _command({"type": "undo"}) + _command({"type": "target", "uid": uid, "policy": 1}) + _check(EconomyManager.get_team(0).roster[0].target_policy == 1, "Targeting policy is persisted in the formation.") + EconomyManager.freeze(1) + GameState.set_phase(GameState.Phase.COMBAT) + var frozen: Dictionary = EconomyManager.get_team(0) + for mutation: Dictionary in [ + {"type": "build", "type_id": "g01", "cell": Vector2i(1, 0)}, + {"type": "upgrade", "uid": uid}, {"type": "sell", "uid": uid}, + {"type": "move", "uid": uid, "cell": Vector2i(1, 0)}, {"type": "worker"}, + {"type": "queue_send", "type_id": "s01"}, {"type": "cancel_send", "index": 0}, + {"type": "target", "uid": uid, "policy": 2}, {"type": "undo"}, + ]: + _command(mutation, false) + _check(EconomyManager.get_team(0) == frozen, "Every economic mutation is rejected during combat.") + + +func _test_send_commit_and_settlement() -> void: + _open_economy_to_wave(3) + var before: Dictionary = EconomyManager.get_team(0) + _check(before.sparks == 30, "Unspent sparks accumulate once per build phase.") + _command({"type": "queue_send", "type_id": "s01"}) + var reserved: Dictionary = EconomyManager.get_team(0) + _check(reserved.sparks == 30 and reserved.income == 20 and reserved.send_queue.size() == 1, + "Queuing reserves sparks without spending them or changing income.") + _command({"type": "queue_send", "type_id": "s01"}, false) + _command({"type": "cancel_send", "index": 0}) + _check(EconomyManager.get_team(0).send_queue.is_empty() and EconomyManager.get_team(0).sparks == 30, + "Cancel releases the entire reservation.") + _command({"type": "undo"}) + _check(EconomyManager.get_team(0) == reserved, "Undo cancellation restores its reservation.") + var queues: Array = EconomyManager.freeze(3) + _check(queues.size() == 2 and queues[0].size() == 1 and queues[0][0] == "s01", + "Freeze returns the send queue for the current combat wave.") + var committed: Dictionary = EconomyManager.get_team(0) + _check(committed.sparks == 10 and committed.income == 23 and committed.send_queue.is_empty(), + "Freeze spends the reservation and permanently increases income once.") + EconomyManager.freeze(3) + _check(EconomyManager.get_team(0) == committed, "Repeated freeze cannot spend or grant income twice.") + EconomyManager.settle(0, 3, 7) + var paid: Dictionary = EconomyManager.get_team(0) + _check(paid.gold == committed.gold + 55 + 6 + 23 + 7, + "Current-wave settlement includes the newly committed income and kill bounty.") + EconomyManager.settle(0, 3, 777) + _check(EconomyManager.get_team(0) == paid, "Duplicate settlement cannot award gold again, even with a changed bounty.") + + +func _ai_wave(number: int, ai, level: int) -> Dictionary: + # Mirrors the WaveManager flow: open, plan against a frozen snapshot, commit. + # Returns the state as planned, before freeze clears the send queue. + GameState.wave = number + GameState.set_phase(GameState.Phase.BUILD) + EconomyManager.open_build(number) + ai.plan(1, number, EconomyManager.get_team(0), GameState.last_reports[1], level) + var own: Dictionary = EconomyManager.get_team(1) + _check(int(own.gold) >= 0 and int(own.sparks) >= 0, + "AI level %d keeps gold and sparks non-negative in wave %d." % [level, number]) + _check(EconomyManager.reserved_sparks(1) <= EconomyManager.send_budget(number), + "AI level %d never reserves more than the wave send budget." % level) + EconomyManager.freeze(number) + EconomyManager.settle(0, number, 0) + EconomyManager.settle(1, number, 5000) + return own + + +func _test_ai_learning_level() -> void: + var selected_level: int = GameState.ai_level + GameState.reset_match() + EconomyManager.reset_match() + var ai = AIScript.new() + _ai_wave(1, ai, GameState.AI_LEARNING) + var opening: Dictionary = EconomyManager.get_team(1) + _check(opening.roster.size() == 3 and opening.workers == 1, + "Learning AI opens with the fixed three-unit formation.") + for number: int in range(2, 9): + var own: Dictionary = _ai_wave(number, ai, GameState.AI_LEARNING) + _check(int(own.workers) + int(own.pending_workers) <= 4, + "Learning AI never exceeds four workers (wave %d)." % number) + _check(own.roster.size() <= 12, + "Learning AI keeps its fixed small board size (wave %d)." % number) + if number % 2 == 0: + _check(own.send_queue.is_empty(), + "Learning AI sends only in every second allowed wave (wave %d)." % number) + elif number >= 3: + _check(not own.send_queue.is_empty(), + "Learning AI spends sparks on every odd allowed wave (wave %d)." % number) + _check(GameState.ai_level == selected_level, + "The learning fixture never silently changes the selected match level.") + + +func _test_ai_standard_level() -> void: + GameState.reset_match() + EconomyManager.reset_match() + var ai = AIScript.new() + var exceeded_learning_cap := false + for number: int in range(1, 9): + var own: Dictionary = _ai_wave(number, ai, GameState.AI_STANDARD) + if number >= 3: + exceeded_learning_cap = exceeded_learning_cap \ + or int(own.workers) + int(own.pending_workers) > 4 + if number >= 5: + _check(not own.send_queue.is_empty(), + "Standard AI queues sends in every allowed wave (wave %d)." % number) + _check(exceeded_learning_cap, + "Standard AI grows its worker economy beyond the learning cap.") + + +func _test_worker_limit_and_last_wave() -> void: + _open_economy_to_wave(1) + # Fund the cap boundary fixture directly; real-budget runs live in the slice acceptance test. + EconomyManager.teams[0].gold = 10000 + for number: int in range(1, DataCatalog.wave_count()): + while true: + var state: Dictionary = EconomyManager.get_team(0) + var count: int = int(state.workers + state.pending_workers) + var price: int = 70 + 20 * (count - 1) + if count >= 8 or int(state.gold) < price: + break + _command({"type": "worker"}) + EconomyManager.freeze(number) + EconomyManager.settle(0, number, 0) + GameState.wave = number + 1 + GameState.set_phase(GameState.Phase.BUILD) + EconomyManager.open_build(number + 1) + var capped: Dictionary = EconomyManager.get_team(0) + _check(capped.workers == 8 and capped.pending_workers == 0, "Worker count never exceeds eight.") + _check(capped.sparks == 400, "Stored sparks cap at 400 and discard overflow.") + _command({"type": "worker"}, false) + _open_economy_to_wave(DataCatalog.wave_count()) + _check(EconomyManager.get_team(0).workers == 1, "Last-wave restriction fixture still has free worker capacity.") + _command({"type": "worker"}, false) + + +func _test_damage_matrix() -> void: + var factors: Array = [[1.30, 0.75, 1.00], [1.00, 1.30, 0.75], [0.75, 1.00, 1.30]] + for attack_type: int in range(3): + for armor_type: int in range(3): + var definition: Dictionary = DataCatalog.get_unit("g01") + definition.max_hp = 10000.0 + definition.armor_type = armor_type + definition.ability = "" + var unit = UnitScript.new() + add_child(unit) + unit.setup(definition, 1, 0, false, Vector2i.ZERO, 0, false) + unit.receive_damage(100.0, attack_type) + _check(is_equal_approx(10000.0 - unit.hp, 100.0 * float(factors[attack_type][armor_type])), + "Damage matrix attack=%d armor=%d applies its expected factor." % [attack_type, armor_type]) + unit.free() + var shielded = UnitScript.new() + add_child(shielded) + var neutral: Dictionary = DataCatalog.get_unit("g01") + neutral.ability = "" + shielded.setup(neutral, 1, 0, false, Vector2i.ZERO, 0, false) + shielded.shield = 30.0 + shielded.receive_damage(50.0, 1) + _check(is_equal_approx(shielded.hp, 240.0) and is_zero_approx(shielded.shield), + "Shields absorb post-matrix damage before HP.") + shielded.free() + + +func _test_leaks_and_timeout() -> void: + var battle = BattleScript.new() + battle.render_enabled = false + add_child(battle) + var attacker: Dictionary = DataCatalog.get_send("s01", 5) + attacker.speed = 0.0 + attacker.damage = 0.0 + attacker.ability = "" + attacker.leak_value = 55 + battle.begin_battle([[], []], [[attacker], [attacker.duplicate(true)]], 5) + for unit in battle.units: + unit.hp = unit.max_hp * 0.5 + battle.elapsed = 89.99 + var result: Dictionary = battle.step(1.0 / 60.0) + _check(bool(result.finished), "Combat timeout finishes both lanes.") + _check(result.leak_damage == [36, 36], "Timeout leaks use ceil(55 * 1.28 * 0.5) = 36 on both lanes.") + _check(result.bounties == [0, 0] and result.leaks == [1, 1], "Timeout leaks yield no kill bounty.") + var repeated: Dictionary = battle.step(1.0 / 60.0) + _check(repeated.leak_damage == [0, 0] and repeated.bounties == [0, 0] and repeated.leaks == [1, 1], + "Finished combat cannot repeat leak damage or rewards.") + battle.free() + + +func _fixture_unit(type_id: String, stable_id: int, lane: int, attacker: bool, + overrides: Dictionary = {}) -> CombatUnit: + var definition: Dictionary = DataCatalog.get_unit(type_id) + definition.merge(overrides, true) + var unit = UnitScript.new() + add_child(unit) + unit.setup(definition, stable_id, lane, attacker, Vector2i.ZERO, 0, false) + return unit + + +func _test_dot_tick_and_refresh() -> void: + var unit = _fixture_unit("g01", 1, 0, false, {"ability": ""}) + # Durchschlag against Leicht is neutral, so each tick removes exactly 4 HP. + unit.apply_dot("test_burn", 4.0, 3.0, 1) + _check(is_equal_approx(unit.hp, 260.0), "Applying a DoT cannot inflict an immediate tick.") + unit.advance_status(0.99) + _check(is_equal_approx(unit.hp, 260.0), "DoT waits one full second before its first tick.") + unit.advance_status(0.01) + _check(is_equal_approx(unit.hp, 256.0), "DoT inflicts its first tick at exactly one second.") + unit.advance_status(1.0) + _check(is_equal_approx(unit.hp, 252.0), "DoT inflicts its second tick at two seconds.") + unit.advance_status(1.0) + _check(is_equal_approx(unit.hp, 248.0) and unit.dots.is_empty(), + "Three-second DoT includes the third boundary tick and then expires.") + unit.advance_status(1.0) + _check(is_equal_approx(unit.hp, 248.0), "Expired DoT cannot tick a fourth time.") + unit.setup(unit.data, 1, 0, false, Vector2i.ZERO, 0, false) + unit.apply_dot("test_burn", 4.0, 3.0, 1) + unit.advance_status(0.5) + unit.apply_dot("test_burn", 4.0, 3.0, 1) + _check(is_equal_approx(unit.hp, 260.0) and unit.dots.size() == 1, + "Refreshing the same DoT neither stacks a second copy nor ticks immediately.") + unit.advance_status(0.5) + _check(is_equal_approx(unit.hp, 256.0), "DoT refresh preserves the original one-second tick rhythm.") + unit.advance_status(2.0) + _check(is_equal_approx(unit.hp, 248.0), "A larger status step executes each due DoT tick exactly once.") + unit.advance_status(0.5) + unit.advance_status(1.0) + _check(is_equal_approx(unit.hp, 248.0) and unit.dots.is_empty(), + "Extending the DoT at half a second creates no extra expiry tick.") + unit.free() + + +func _test_shield_replacement() -> void: + var unit = _fixture_unit("g01", 1, 0, false, {"ability": ""}) + unit.grant_shield(100.0, 4.0) + unit.advance_status(1.0) + unit.grant_shield(60.0, 8.0) + _check(is_equal_approx(unit.shield, 100.0) and is_equal_approx(unit.shield_remaining, 3.0), + "A weaker shield neither stacks nor extends the stronger shield's duration.") + unit.grant_shield(100.0, 8.0) + _check(is_equal_approx(unit.shield, 100.0) and is_equal_approx(unit.shield_remaining, 3.0), + "An equal shield does not replace the strongest remaining shield.") + unit.receive_damage(50.0, 1) + unit.grant_shield(60.0, 2.0) + _check(is_equal_approx(unit.hp, 260.0) and is_equal_approx(unit.shield, 60.0) + and is_equal_approx(unit.shield_remaining, 2.0), + "Replacement compares remaining shield strength and replaces, rather than adds, protection.") + unit.advance_status(2.0) + _check(is_zero_approx(unit.shield), "A timed replacement shield expires at its own boundary.") + unit.free() + + +func _test_fourth_hit_bonus() -> void: + var lancer = _fixture_unit("g05", 1, 0, false) + var victim = _fixture_unit("g01", 2000000, 0, true, + {"ability": "", "max_hp": 1000.0}) + victim.position = Vector3(0, 0, 1) + lancer.target = victim + var combatants: Array = [lancer, victim] + lancer.attack_component.step(lancer, combatants, 0.99) + _check(is_equal_approx(victim.hp, 1000.0) and lancer.attack_component.hit_count == 0, + "Entering attack range does not grant an instant first attack.") + lancer.attack_component.step(lancer, combatants, 0.01) + lancer.attack_component.step(lancer, combatants, 1.0) + lancer.attack_component.step(lancer, combatants, 1.0) + _check(is_equal_approx(victim.hp, 928.0) and lancer.attack_component.hit_count == 3, + "The first three Funkenlanze hits each inflict 24 neutral damage.") + lancer.attack_component.step(lancer, combatants, 1.0) + _check(is_equal_approx(victim.hp, 892.0) and lancer.attack_component.hit_count == 4, + "Fourth hit inflicts 36 damage and increments the primary hit counter only once.") + lancer.attack_component.step(lancer, combatants, 1.0) + _check(is_equal_approx(victim.hp, 868.0) and lancer.attack_component.hit_count == 5, + "The bonus cannot recurse or shift the following ordinary attack.") + lancer.free() + victim.free() + + +func _test_splash_limit_and_lane_isolation() -> void: + var source = _fixture_unit("g07", 1, 0, false) + # Impuls against Schwer is neutral. A basic hit is 23; each splash is 6.9. + var target_overrides: Dictionary = {"ability": "", "armor_type": 1, "max_hp": 1000.0} + var primary = _fixture_unit("g01", 2000000, 0, true, target_overrides) + primary.position = Vector3(0, 0, 1) + source.target = primary + var combatants: Array = [source, primary] + var extras: Array = [] + for index: int in range(4): + var extra = _fixture_unit("g01", 2000001 + index, 0, true, target_overrides) + extra.position = primary.position + Vector3(float(index + 1) * 0.1, 0, 0) + extras.append(extra) + combatants.append(extra) + var other_lane = _fixture_unit("g01", 2100000, 1, true, target_overrides) + other_lane.position = primary.position + var ally = _fixture_unit("g01", 2, 0, false, target_overrides) + ally.position = primary.position + combatants.append(other_lane) + combatants.append(ally) + source.attack_component.step(source, combatants, 1.0) + _check(is_equal_approx(primary.hp, 977.0), "Splash excludes its primary target from bonus damage.") + for index: int in range(3): + _check(is_equal_approx(extras[index].hp, 993.1), + "Splash applies exactly 30 percent damage to nearby extra target %d." % index) + _check(is_equal_approx(extras[3].hp, 1000.0), "Glutpakt splash stops after three additional targets.") + _check(is_equal_approx(other_lane.hp, 1000.0) and is_equal_approx(ally.hp, 1000.0), + "Splash ignores the other lane and allied guardians even when their positions overlap.") + _check(source.attack_component.hit_count == 1, "Splash events do not advance the primary attack counter.") + for unit in combatants: + unit.free() + + +func _test_identity_and_formation_reset() -> void: + var battle = BattleScript.new() + battle.render_enabled = false + add_child(battle) + var rosters: Array = [ + [{"uid": 1, "type_id": "g01", "cell": Vector2i(2, 3), "invested": 45, "target_policy": 2}], + [{"uid": 1000001, "type_id": "g01", "cell": Vector2i.ZERO, "invested": 45, "target_policy": 0}], + ] + var attackers: Array = [DataCatalog.get_attackers(1), DataCatalog.get_attackers(1)] + battle.begin_battle(rosters, attackers, 1) + var identities: Dictionary = {} + var all_unique: bool = true + var guardian: CombatUnit + for unit in battle.units: + if identities.has(unit.uid): + all_unique = false + identities[unit.uid] = true + if unit.uid == 1: + guardian = unit + _check(all_unique and identities.size() == 18, + "Both guardian teams and all 16 attackers have distinct stable IDs.") + _check(identities.has(1000001) and identities.has(2000001), + "Lane-zero attackers cannot reuse the team-one guardian namespace.") + guardian.hp = 13.0 + guardian.grant_shield(80.0, 50.0) + guardian.apply_effect("temporary", "damage", 0.15, 50.0) + guardian.apply_dot("burn", 4.0, 3.0, 1) + guardian.attack_component.progress = 0.75 + guardian.attack_component.hit_count = 99 + guardian.ability_component.ready_time = 42.0 + guardian.combat_time = 20.0 + guardian.target = battle.units[2] + guardian.position = Vector3(0, 0, 10) + guardian.alive = false + battle.show_formation(rosters) + var restored: CombatUnit = battle.units[0] + _check(restored.alive and is_equal_approx(restored.hp, 260.0) and is_zero_approx(restored.shield), + "Formation restoration revives guardians at full HP and clears combat shields.") + _check(restored.effects.is_empty() and restored.dots.is_empty() and restored.target == null, + "Formation restoration discards buffs, DoTs and old targets.") + _check(restored.attack_component.hit_count == 0 and is_zero_approx(restored.attack_component.progress) + and is_equal_approx(restored.ability_component.ready_time, 6.0) and is_zero_approx(restored.combat_time), + "Formation restoration resets attack counts, cooldowns and ability timers.") + _check(restored.uid == 1 and restored.home_cell == Vector2i(2, 3) and restored.target_policy == 2 + and restored.position == Vector3(-10, 0, -1) and int(rosters[0][0].invested) == 45, + "Restoration preserves identity, build cell, target policy and investment.") + _check(battle.units.size() == 2, "Rebuilding a formation removes every prior-wave attacker.") + battle.free() + + +func _test_core_resolution() -> void: + GameState.reset_match() + GameState.apply_core_damage([4000, 4000]) + _check(GameState.core_hp == [0, 0], "Core damage clamps both cores to zero in one batch.") + _check(GameState.decide_winner(false) == -1, "Both cores dying in the same tick is a draw.") + GameState.reset_match() + _check(GameState.core_hp == [3000, 3000] and GameState.outcome == -2 + and not GameState.paused and GameState.speed == 1.0, + "A new match clears damage, outcome, pause and speed.") + _check(GameState.decide_winner(false) == -2, "Equal surviving cores do not end an earlier wave.") + GameState.apply_core_damage([0, 100]) + _check(GameState.decide_winner(true) == 0, "Final wave selects the surviving core with more HP.") + GameState.reset_match() + _check(GameState.decide_winner(true) == -1, "Equal surviving cores draw after the final wave.") + + +func _test_slice_lifecycle() -> void: + var battle = BattleScript.new() + battle.render_enabled = false + add_child(battle) + WaveManager.attach_battle(battle) + WaveManager.start_match() + # Keep this lifecycle fixture alive regardless of balance. Shorten only the + # controller clock; each boundary still executes a real production tick. + GameState.core_hp = [3000000, 3000000] + for number: int in range(1, DataCatalog.wave_count() + 1): + _check(GameState.wave == number and GameState.phase == GameState.Phase.BUILD, + "Wave %d begins in BUILD." % number) + if GameState.phase != GameState.Phase.BUILD: + break + WaveManager.ready_for_battle() + _check(GameState.phase == GameState.Phase.COMBAT, "Ready enters COMBAT for wave %d." % number) + battle.elapsed = 89.99 + WaveManager.advance(1.0 / 30.0) + _check(GameState.phase == GameState.Phase.RESULTS or GameState.phase == GameState.Phase.GAME_OVER, + "Finishing wave %d reaches results or match end." % number) + if GameState.phase == GameState.Phase.RESULTS: + WaveManager.advance(4.1) + _check(GameState.wave == DataCatalog.wave_count() and GameState.phase == GameState.Phase.GAME_OVER and GameState.outcome != -2, + "Final wave terminates the complete match with a resolved outcome.") + WaveManager.start_match() + _check(GameState.wave == 1 and GameState.phase == GameState.Phase.BUILD and GameState.core_hp == [3000, 3000], + "Restart after the last wave creates a fresh playable first wave.") + battle.free() diff --git a/tests/test_runner.gd.uid b/tests/test_runner.gd.uid new file mode 100644 index 0000000..e83cb76 --- /dev/null +++ b/tests/test_runner.gd.uid @@ -0,0 +1 @@ +uid://buq33oej6g8vl diff --git a/tests/test_runner.tscn b/tests/test_runner.tscn new file mode 100644 index 0000000..3472c40 --- /dev/null +++ b/tests/test_runner.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tests/test_runner.gd" id="1_tests"] + +[node name="TestRunner" type="Node"] +script = ExtResource("1_tests") diff --git a/tools/__pycache__/build_demo.cpython-314.pyc b/tools/__pycache__/build_demo.cpython-314.pyc new file mode 100644 index 0000000..0cfd0c2 Binary files /dev/null and b/tools/__pycache__/build_demo.cpython-314.pyc differ diff --git a/tools/__pycache__/prepare_phase3_assets.cpython-314.pyc b/tools/__pycache__/prepare_phase3_assets.cpython-314.pyc new file mode 100644 index 0000000..934f00f Binary files /dev/null and b/tools/__pycache__/prepare_phase3_assets.cpython-314.pyc differ diff --git a/tools/__pycache__/verify_phase4_glb.cpython-314.pyc b/tools/__pycache__/verify_phase4_glb.cpython-314.pyc new file mode 100644 index 0000000..be05c19 Binary files /dev/null and b/tools/__pycache__/verify_phase4_glb.cpython-314.pyc differ diff --git a/tools/arbeiter_review.gd b/tools/arbeiter_review.gd new file mode 100644 index 0000000..3c30928 --- /dev/null +++ b/tools/arbeiter_review.gd @@ -0,0 +1,32 @@ +extends Node +## Real in-game inspector captures for the Funkenleser work clips. +var main: Node3D +var captures := "res://docs/screenshots/phase12" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures+"/"+name+".png") +func run() -> void: + get_window().size = Vector2i(1600,1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("worker") + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + studio._turntable.rotation.y = -.1 + await shot("arbeiter-front") + studio._turntable.rotation.y = PI + await shot("arbeiter-back") + studio._turntable.rotation.y = -.1 + for clip: String in ["walk","strike","pickup","deposit","return","death"]: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip: studio._clip_selector.select(i) + studio._clip_time = .55 if clip == "walk" else (.80 if clip == "strike" else (1.2 if clip == "death" else .55)) + await shot("pose-"+clip) + print("ARBEITER_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/arbeiter_review.gd.uid b/tools/arbeiter_review.gd.uid new file mode 100644 index 0000000..44ca72e --- /dev/null +++ b/tools/arbeiter_review.gd.uid @@ -0,0 +1 @@ +uid://dwycls076yrvx diff --git a/tools/arbeiter_review.tscn b/tools/arbeiter_review.tscn new file mode 100644 index 0000000..c8088ef --- /dev/null +++ b/tools/arbeiter_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8arbeiterreview"] + +[ext_resource type="Script" path="res://tools/arbeiter_review.gd" id="1"] + +[node name="ArbeiterReview" type="Node"] +script = ExtResource("1") diff --git a/tools/balance_sim.gd b/tools/balance_sim.gd new file mode 100644 index 0000000..3677d4f --- /dev/null +++ b/tools/balance_sim.gd @@ -0,0 +1,164 @@ +extends Node +## Headless balance sweep over complete AI-vs-AI matches. +## Run: godot --headless --path . res://tools/balance_sim.tscn +## Mirrors the WaveManager flow with both seats driven by SimpleAI levels; +## stepping, economy and combat are the production implementations. + +const AIScript = preload("res://scripts/ai/simple_ai.gd") +const BattleScript = preload("res://scripts/combat/battle_controller.gd") +const STEP: float = 1.0 / 60.0 +const LEVEL_NAMES: Array[String] = ["Lernmodus", "Standard"] + +var violations: Array[String] = [] +var _public_snapshots: Array = [{}, {}] + + +func _ready() -> void: + WaveManager.set_physics_process(false) + call_deferred("_run") + + +func _run() -> void: + var started := Time.get_ticks_msec() + var lines: Array[String] = [] + lines.append("# Saumwacht · Balance-Sweep") + lines.append("") + lines.append("Erzeugt von `tools/balance_sim.gd`; KI-Partien mit der aktuellen") + lines.append("Wirtschaft und Kampfsimulation (fester 1/60-Schritt, feste Startzustände).") + for matchup: Array in [ + ["Standard gegen Standard", GameState.AI_STANDARD, GameState.AI_STANDARD], + ["Lernmodus gegen Standard", GameState.AI_LEARNING, GameState.AI_STANDARD], + ]: + lines.append_array(_play_match(matchup[0], matchup[1], matchup[2])) + lines.append("") + lines.append("Keine Verletzung der im Sweep geprüften Invarianten." + if violations.is_empty() else + "VERLETZUNGEN: " + "; ".join(violations)) + print("\n".join(lines)) + print("Balance-Sweep fertig in %.1f s." % ((Time.get_ticks_msec() - started) / 1000.0)) + get_tree().quit(0 if violations.is_empty() else 1) + + +func _play_match(title: String, level0: int, level1: int) -> Array[String]: + GameState.reset_match() + EconomyManager.reset_match() + _public_snapshots = [EconomyManager.get_team(0), EconomyManager.get_team(1)] + GameState.wave = 1 + var battle = BattleScript.new() + battle.render_enabled = false + add_child(battle) + var ai = AIScript.new() + var lines: Array[String] = [] + lines.append("") + lines.append("## %s" % title) + lines.append("") + lines.append("| Welle | Dauer s | Lecks 0/1 | Kernschaden 0/1 | Abschussprämien 0/1 | Goldbestand 0/1 | Wächter 0/1 | Abgerechnet |") + lines.append("| ---: | ---: | ---: | ---: | ---: | ---: | ---: | :---: |") + var winner: int = GameState.ONGOING + var total_leaks: Array[int] = [0, 0] + var total_seconds: float = 0.0 + while GameState.wave <= DataCatalog.wave_count(): + var wave: int = GameState.wave + var report: Dictionary = _play_wave(battle, ai, wave, level0, level1) + total_leaks[0] += int(report.leaks[0]) + total_leaks[1] += int(report.leaks[1]) + total_seconds += float(report.combat_seconds) + _check_state(wave) + lines.append("| %d | %.1f | %d/%d | %d/%d | %d/%d | %d/%d | %d/%d | %s |" % [ + wave, float(report.combat_seconds), + report.leaks[0], report.leaks[1], + report.core_damage[0], report.core_damage[1], + report.bounty[0], report.bounty[1], + EconomyManager.get_team(0).gold, EconomyManager.get_team(1).gold, + EconomyManager.get_team(0).roster.size(), EconomyManager.get_team(1).roster.size(), + "Ja" if report.settled else "Nein"]) + winner = GameState.decide_winner(wave == DataCatalog.wave_count()) + if winner != GameState.ONGOING: + break + GameState.wave += 1 + var outcome: String + match winner: + GameState.DRAW: outcome = "Unentschieden" + 0: outcome = "Front 0 gewinnt (%s)" % LEVEL_NAMES[level0] + 1: outcome = "Front 1 gewinnt (%s)" % LEVEL_NAMES[level1] + _: + outcome = "Unbeendet" + violations.append("%s: kein Matchende innerhalb der vorgesehenen Wellen." % title) + lines.append("") + lines.append("**Ergebnis nach %d Wellen:** %s · Kern %d/%d HP · Lecks gesamt %d/%d · mittlere Kampfdauer %.1f s" % [ + GameState.wave, outcome, GameState.core_hp[0], GameState.core_hp[1], + total_leaks[0], total_leaks[1], total_seconds / float(maxi(1, GameState.wave))]) + battle.free() + return lines + + +func _play_wave(battle, ai, wave: int, level0: int, level1: int) -> Dictionary: + EconomyManager.open_build(wave) + ai.plan(0, wave, _public_snapshots[1], GameState.last_reports[0], level0) + ai.plan(1, wave, _public_snapshots[0], GameState.last_reports[1], level1) + _public_snapshots = [EconomyManager.get_team(0), EconomyManager.get_team(1)] + _check_build_orders(wave) + var outgoing: Array = EconomyManager.freeze(wave) + var attackers: Array = [DataCatalog.get_attackers(wave), DataCatalog.get_attackers(wave)] + var natural_count: int = attackers[0].size() + for sender: int in range(2): + for send_id: String in outgoing[sender]: + attackers[1 - sender].append(DataCatalog.get_send(send_id, wave)) + battle.begin_battle([EconomyManager.get_team(0).roster, EconomyManager.get_team(1).roster], + attackers, wave) + var report: Dictionary = {} + var wave_core_damage: Array[int] = [0, 0] + while true: + report = battle.step(STEP) + if report.leak_damage[0] > 0 or report.leak_damage[1] > 0: + for team: int in range(2): + wave_core_damage[team] += int(report.leak_damage[team]) + GameState.apply_core_damage(report.leak_damage) + if GameState.decide_winner(false) != GameState.ONGOING or bool(report.finished): + break + # WaveManager checks core death before settlement, including the final step. + var did_settle: bool = GameState.decide_winner(false) == GameState.ONGOING and bool(report.finished) + if did_settle: + var reports: Array = [] + for team: int in range(2): + var settled: Dictionary = EconomyManager.settle(team, wave, int(report.bounties[team])) + settled["leaks"] = report.leaks[team] + settled["core_damage"] = wave_core_damage[team] + settled["combat_seconds"] = report.elapsed + settled["natural_count"] = natural_count + settled["natural_leaks"] = report.natural_leaks[team] + settled["front_lifetime"] = report.front_lifetime[team] + reports.append(settled) + GameState.last_reports = reports + if float(report.elapsed) > 90.001: + violations.append("Welle %d: Kampf über 90 s." % wave) + return { + "leaks": report.leaks, "core_damage": wave_core_damage, + "bounty": report.bounties, "combat_seconds": report.elapsed, "settled": did_settle} + + +func _check_build_orders(wave: int) -> void: + for team: int in range(2): + var own: Dictionary = EconomyManager.get_team(team) + var reserved: int = EconomyManager.reserved_sparks(team) + if own.send_queue.size() > EconomyManager.MAX_SENDS or reserved > EconomyManager.send_budget(wave): + violations.append("Welle %d: Team %d überschreitet ein Sendlimit." % [wave, team]) + if reserved > int(own.sparks): + violations.append("Welle %d: Team %d reserviert mehr Funken als vorhanden." % [wave, team]) + + +func _check_state(wave: int) -> void: + for team: int in range(2): + var own: Dictionary = EconomyManager.get_team(team) + if int(own.gold) < 0 or int(own.sparks) < 0: + violations.append("Welle %d: Team %d mit negativer Ressource." % [wave, team]) + if own.roster.size() > EconomyManager.GRID_SIZE.x * EconomyManager.GRID_SIZE.y: + violations.append("Welle %d: Team %d überfüllt das Baufeld." % [wave, team]) + var occupied: Array[Vector2i] = [] + for entry: Dictionary in own.roster: + var cell: Vector2i = entry.cell + if occupied.has(cell) or cell.x < 0 or cell.y < 0 or cell.x >= EconomyManager.GRID_SIZE.x or cell.y >= EconomyManager.GRID_SIZE.y: + violations.append("Welle %d: Team %d hat eine ungültige Zellbelegung." % [wave, team]) + occupied.append(cell) + if int(own.workers) + int(own.pending_workers) > EconomyManager.MAX_WORKERS or int(own.sparks) > EconomyManager.SPARK_CAP: + violations.append("Welle %d: Team %d überschreitet eine Ressourcengrenze." % [wave, team]) diff --git a/tools/balance_sim.gd.uid b/tools/balance_sim.gd.uid new file mode 100644 index 0000000..c558f82 --- /dev/null +++ b/tools/balance_sim.gd.uid @@ -0,0 +1 @@ +uid://cy0q7xq1jbi1i diff --git a/tools/balance_sim.tscn b/tools/balance_sim.tscn new file mode 100644 index 0000000..648e23f --- /dev/null +++ b/tools/balance_sim.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/balance_sim.gd" id="1_balance"] + +[node name="BalanceSim" type="Node"] +script = ExtResource("1_balance") diff --git a/tools/basalt_review.gd b/tools/basalt_review.gd new file mode 100644 index 0000000..ed6ba63 --- /dev/null +++ b/tools/basalt_review.gd @@ -0,0 +1,33 @@ +extends Node +## Capture Basaltbastion review stills. +var main: Node3D +var captures := "res://docs/screenshots/phase15" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") +func run() -> void: + get_window().size = Vector2i(1600, 1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("g04") + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + studio._turntable.rotation.y = -.15 + await shot("basalt-front") + studio._turntable.rotation.y = PI + await shot("basalt-back") + studio._turntable.rotation.y = -.15 + for clip: String in ["walk", "attack_a", "attack_b", "ability", "death"]: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip: + studio._clip_selector.select(i) + studio._clip_time = .55 if clip == "walk" else (.9 if clip.begins_with("attack") else (1.0 if clip == "ability" else 1.2)) + await shot("pose-" + clip) + print("BASALT_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/basalt_review.gd.uid b/tools/basalt_review.gd.uid new file mode 100644 index 0000000..2ba74ab --- /dev/null +++ b/tools/basalt_review.gd.uid @@ -0,0 +1 @@ +uid://l17wab0m4fdw diff --git a/tools/basalt_review.tscn b/tools/basalt_review.tscn new file mode 100644 index 0000000..553b5af --- /dev/null +++ b/tools/basalt_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8basaltreview"] + +[ext_resource type="Script" path="res://tools/basalt_review.gd" id="1"] + +[node name="BasaltReview" type="Node"] +script = ExtResource("1") diff --git a/tools/build_asset_gallery.py b/tools/build_asset_gallery.py new file mode 100644 index 0000000..1064cfc --- /dev/null +++ b/tools/build_asset_gallery.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 +"""Build the offline Phase 3 gallery; run from any working directory. + +Reads the plan, records and PNG headers only. Native image bytes are never edited. +Usage: python3 /path/to/saumwacht-godot/tools/build_asset_gallery.py +""" + +from __future__ import annotations + +import html +import json +import os +from pathlib import Path +import struct +import sys +from urllib.parse import quote + + +PROJECT = Path(__file__).resolve().parents[1] +ASSET_ROOT = PROJECT / "assets-source" / "phase3" +OUTPUT = ASSET_ROOT / "gallery.html" +FACTIONS = { + "glutpakt": "Glutpakt", + "nietenkonvent": "Nietenkonvent", + "nebelchor": "Nebelchor", + "wurzelbund": "Wurzelbund", + "neutral": "Neutrale", + "resources": "Ressourcen", + "types": "Schaden & Rüstung", + "map": "Karte", + "ui": "Oberfläche", +} +KINDS = { + "unit_icon": "Einheitenicon", + "mercenary_icon": "Söldnericon", + "resource_icon": "Ressourcenicon", + "worker_icon": "Arbeitericon", + "type_icon": "Typicon", + "map_concept": "Kartenkonzept", + "tile_concept": "Bodenkachel", + "ui_frame": "UI-Rahmen", + "ui_button": "Button", +} + + +def esc(value: object) -> str: + return html.escape(str(value), quote=True) + + +def local_url(path: Path) -> str: + return quote(Path(os.path.relpath(path, ASSET_ROOT)).as_posix(), safe="/.") + + +def png_size(path: Path) -> tuple[int, int] | None: + """Inspect the native PNG header without decoding or changing pixels.""" + try: + with path.open("rb") as source: + header = source.read(24) + if len(header) == 24 and header[:8] == b"\x89PNG\r\n\x1a\n" and header[12:16] == b"IHDR": + return struct.unpack(">II", header[16:24]) + except OSError: + pass + return None + + +def read_assets() -> list[dict]: + plan = json.loads((ASSET_ROOT / "asset_plan.json").read_text(encoding="utf-8")) + assets = [] + for planned in plan["assets"]: + asset = dict(planned) + record_path = ASSET_ROOT / "records" / f"{planned['id']}.json" + record = {} + issue = "Datensatz und Bild stehen noch aus." + if record_path.is_file(): + try: + record = json.loads(record_path.read_text(encoding="utf-8")) + if not isinstance(record, dict) or record.get("id") != planned["id"]: + raise ValueError("Datensatz-ID stimmt nicht mit dem Plan überein") + except (OSError, ValueError) as error: + print(f"Hinweis: {record_path.name}: {error}", file=sys.stderr) + record = {} + issue = "Datensatz ist noch nicht lesbar." + asset.update(record) + asset["id"] = planned["id"] + master = None + if record.get("master_path"): + given = Path(record["master_path"]) + candidates = [given] if given.is_absolute() else [ASSET_ROOT / given, PROJECT / given] + # Keep a copied project usable when records retain their original absolute paths. + if "masters" in given.parts: + index = given.parts.index("masters") + candidates.insert(0, ASSET_ROOT.joinpath(*given.parts[index:])) + master = next((path for path in candidates if path.is_file()), None) + issue = "Originaldatei fehlt noch im Projekt." + size = png_size(master) if master else None + if master and not size: + issue = "Originaldatei ist noch kein lesbares PNG." + asset["ready"] = bool(record and master and size) + asset["issue"] = issue + asset["image_url"] = local_url(master) if asset["ready"] else "" + asset["record_url"] = local_url(record_path) if record else "" + asset["dimensions"] = size + assets.append(asset) + return assets + + +def card(asset: dict) -> str: + asset_id = asset["id"] + name = asset.get("display_name", asset_id) + faction = asset.get("faction", "unknown") + kind = asset.get("kind", "unknown") + faction_name = FACTIONS.get(faction, faction) + kind_name = KINDS.get(kind, kind) + description = asset.get("description_de", "Beschreibung folgt mit dem erzeugten Asset.") + ready = asset["ready"] + state = "ready" if ready else "pending" + is_icon = kind.endswith("_icon") + dimensions = asset["dimensions"] + wide = not is_icon and (kind == "map_concept" or (dimensions and dimensions[0] / dimensions[1] > 1.6)) + classes = "asset-card" + (" wide-card" if wide else "") + (" pending-card" if not ready else "") + search = " ".join(str(item) for item in (asset_id, name, faction_name, kind_name, description)) + if ready: + width, height = dimensions + preview = f''' + {esc(name)} + ''' + size_label = f"{width} × {height} px" + links = f'''PNG-Original + Datensatz ''' + else: + preview = '
Ausstehend' + esc(asset["issue"]) + '
' + size_label = "Noch kein Original" + links = f'Datensatz ↗' if asset["record_url"] else "" + alpha = "Alpha vorgesehen" if asset.get("requires_alpha") else "Flächiges Motiv" + prompt = asset.get("prompt") + prompt_html = f'
Generierungsprompt
{esc(prompt)}
' if prompt else '

Prompt folgt mit dem Datensatz.

' + stage_class = "icon-stage" if is_icon else "media-stage" + return f'''
+
{esc(asset_id)} {"Vorhanden" if ready else "Ausstehend"}
+
{preview}
+

{esc(faction_name)} {esc(kind_name)}

+

{esc(name)}

{esc(description)}

+ + {prompt_html} +
+
''' + + +CSS = r""" +:root { color-scheme: dark; --page:#101a20; --panel:#18262e; --line:#30424a; --ink:#edf0e9; --muted:#a9b9b8; --gold:#d9b66b; --mint:#82dbce; --icon-size:128px; } +* { box-sizing:border-box; } +body { margin:0; background:var(--page); color:var(--ink); font:15px/1.55 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; } +button,input,select { font:inherit; } +button,select { cursor:pointer; } +a { color:var(--mint); text-underline-offset:4px; } +a:hover { color:#fff; } +:focus-visible { outline:3px solid var(--mint); outline-offset:4px; } +.skip { position:absolute; top:-100px; left:20px; padding:12px; background:var(--page); z-index:20; } +.skip:focus { top:10px; } +.shell { max-width:1580px; margin:0 auto; padding:0 36px; } +.hero { padding:48px 0 28px; display:flex; gap:36px; justify-content:space-between; align-items:flex-end; border-bottom:1px solid var(--line); } +.kicker { margin:0 0 12px; color:var(--gold); text-transform:uppercase; letter-spacing:.2em; font-size:11px; font-weight:750; } +h1 { margin:0; font-size:clamp(36px,5vw,66px); letter-spacing:-.045em; line-height:1.05; font-weight:650; } +.intro { margin:18px 0 0; color:var(--muted); max-width:700px; } +.stats { display:flex; gap:32px; margin:0 0 2px; flex-shrink:0; } +.stats div { min-width:68px; display:flex; flex-direction:column; } +.stats dt { color:var(--muted); font-size:11px; text-transform:uppercase; letter-spacing:.1em; } +.stats dd { order:-1; margin:0 0 6px; font-size:35px; line-height:1; color:var(--gold); font-variant-numeric:tabular-nums; } +.toolbar { margin:26px 0 0; padding:22px; background:var(--panel); border:1px solid var(--line); border-radius:14px; } +.filter-row { display:grid; grid-template-columns:minmax(220px,2fr) repeat(3,minmax(155px,1fr)); gap:14px; } +label { display:block; color:var(--muted); font-size:12px; font-weight:600; } +input,select { display:block; width:100%; height:44px; margin-top:7px; border:1px solid #41545c; border-radius:7px; background:#111e25; color:var(--ink); padding:0 12px; } +input::placeholder { color:#859a9e; } +.view-row { display:flex; flex-wrap:wrap; align-items:center; gap:20px 30px; border-top:1px solid var(--line); padding-top:18px; margin-top:18px; } +fieldset { display:flex; gap:4px; padding:0; border:0; margin:0; min-width:0; } +legend { padding:0; margin-bottom:8px; color:var(--muted); font-size:12px; } +.choice { min-height:36px; padding:6px 12px; color:var(--muted); border:1px solid #41545c; border-radius:6px; background:transparent; } +.choice[aria-pressed="true"] { background:#294844; color:#dafff5; border-color:#71b7a9; } +.choice:hover { border-color:var(--gold); color:var(--ink); } +.view-note { font-size:12px; color:var(--muted); margin:20px 0 0; flex:1; min-width:170px; } +.results-line { display:flex; gap:16px; align-items:center; justify-content:space-between; padding:24px 0 16px; } +#result-count { color:var(--muted); margin:0; font-size:13px; } +.reset { color:var(--mint); background:none; border:0; padding:6px 0; font-size:13px; } +.gallery { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:20px; align-items:start; } +.asset-card { min-width:0; overflow:hidden; border:1px solid var(--line); border-radius:12px; background:var(--panel); } +.asset-card:hover { border-color:#637968; } +.wide-card { grid-column:span 2; } +.card-top { padding:11px 16px; display:flex; justify-content:space-between; gap:10px; align-items:center; } +code { color:#bac9c8; font:12px/1.5 ui-monospace,SFMono-Regular,Consolas,monospace; } +.status { font-size:10px; letter-spacing:.025em; white-space:nowrap; } +.status span { font-size:8px; margin-right:3px; } +.status.ready { color:var(--mint); } +.status.pending { color:var(--gold); } +.preview-stage { display:flex; align-items:center; justify-content:center; overflow:hidden; border-top:1px solid #ffffff09; border-bottom:1px solid #ffffff09; background-color:#26343d; } +body[data-background="checker"] .preview-stage { background-color:#33434b; background-image:linear-gradient(45deg,#27353d 25%,transparent 25%),linear-gradient(-45deg,#27353d 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#27353d 75%),linear-gradient(-45deg,transparent 75%,#27353d 75%); background-size:24px 24px; background-position:0 0,0 12px,12px -12px,-12px 0; } +body[data-background="light"] .preview-stage { background-color:#edf0e8; background-image:none; } +body[data-background="dark"] .preview-stage { background-color:#0a1118; background-image:none; } +.icon-stage { height:286px; padding:14px; } +.preview-link { display:flex; width:100%; height:100%; align-items:center; justify-content:center; } +.preview-link img { display:block; object-fit:contain; max-width:100%; } +.icon-stage img { width:var(--icon-size); height:auto; max-height:var(--icon-size); } +.media-stage { min-height:230px; padding:18px; } +.media-stage .preview-link { height:auto; } +.media-stage img { width:auto; height:auto; max-width:100%; max-height:390px; } +.card-content { padding:18px; } +.eyebrow { color:var(--gold); text-transform:uppercase; font-size:10px; letter-spacing:.09em; margin:0 0 8px; } +.eyebrow span { color:#64797b; margin:0 5px; } +h2 { font-size:20px; line-height:1.2; letter-spacing:-.025em; margin:0 0 11px; } +.description { font-size:13px; color:#b7c7c7; line-height:1.6; margin:0 0 16px; min-height:62px; } +.metadata { display:flex; flex-wrap:wrap; gap:6px; font-size:10px; color:var(--muted); } +.metadata span { border:1px solid #3c4d52; border-radius:4px; padding:3px 6px; } +details { margin-top:16px; padding-top:12px; border-top:1px solid var(--line); } +summary { font-size:12px; cursor:pointer; color:#d5dfd9; } +pre { white-space:pre-wrap; overflow-wrap:anywhere; font:12px/1.6 ui-monospace,SFMono-Regular,Consolas,monospace; color:#b9cbc6; margin:12px 0 0; } +.card-links { display:flex; flex-wrap:wrap; gap:16px; margin-top:15px; font-size:12px; } +.card-links a { text-decoration:none; } +.card-links a:hover { text-decoration:underline; } +.prompt-pending { font-size:12px; color:var(--muted); margin:16px 0 0; } +.placeholder { display:flex; flex-direction:column; gap:6px; align-items:center; text-align:center; color:#c6b88f; max-width:220px; padding:20px; background:#152229de; border:1px dashed #6d735f; border-radius:8px; } +.placeholder-mark { font-size:35px; line-height:1.2; } +.placeholder strong { font-size:14px; font-weight:550; } +.placeholder span:last-child { font-size:11px; } +.pending-card { border-style:dashed; } +.empty { padding:64px 24px; text-align:center; border:1px dashed var(--line); border-radius:12px; color:var(--muted); } +.empty strong { display:block; color:var(--ink); font-size:21px; margin-bottom:8px; } +footer { padding:32px 0 40px; color:#8ba3a5; font-size:12px; display:flex; justify-content:space-between; gap:20px; } +footer p { margin:0; } +noscript p { color:var(--gold); border:1px solid var(--gold); border-radius:8px; padding:12px; } +[hidden] { display:none !important; } +@media (max-width:1050px) { .hero { align-items:flex-start; flex-direction:column; gap:24px; } .stats { gap:40px; } .filter-row { grid-template-columns:repeat(2,minmax(0,1fr)); } } +@media (max-width:680px) { .shell { padding:0 18px; } .hero { padding-top:32px; } .toolbar { padding:16px; } .filter-row { grid-template-columns:1fr; } .gallery { grid-template-columns:1fr; } .wide-card { grid-column:auto; } .stats { gap:24px; } .stats dd { font-size:28px; } .results-line { align-items:flex-start; } footer { flex-direction:column; } } +@media (prefers-reduced-motion:no-preference) { .asset-card,.choice { transition:border-color .15s ease,background-color .15s ease; } } +""" + + +JS = r""" +(() => { + const cards = [...document.querySelectorAll('.asset-card')]; + const search = document.getElementById('search'); + const faction = document.getElementById('faction'); + const kind = document.getElementById('kind'); + const state = document.getElementById('state'); + const count = document.getElementById('result-count'); + const normalize = value => value.toLocaleLowerCase('de').normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/ß/g, 'ss'); + const texts = new Map(cards.map(card => [card, normalize(card.dataset.search)])); + function filter() { + const terms = normalize(search.value).trim().split(/\s+/).filter(Boolean); + let visible = 0; + let ready = 0; + for (const card of cards) { + const match = (!faction.value || card.dataset.faction === faction.value) + && (!kind.value || card.dataset.kind === kind.value) + && (!state.value || card.dataset.state === state.value) + && terms.every(term => texts.get(card).includes(term)); + card.hidden = !match; + if (match) { visible++; if (card.dataset.state === 'ready') ready++; } + } + count.textContent = `${visible} von ${cards.length} Assets · ${ready} vorhanden · ${visible - ready} ausstehend`; + document.getElementById('empty').hidden = visible !== 0; + } + search.addEventListener('input', filter); + for (const select of [faction, kind, state]) select.addEventListener('change', filter); + document.getElementById('reset').addEventListener('click', () => { + search.value = ''; faction.value = ''; kind.value = ''; state.value = ''; filter(); search.focus(); + }); + for (const button of document.querySelectorAll('[data-background-choice]')) { + button.addEventListener('click', () => { + document.body.dataset.background = button.dataset.backgroundChoice; + document.querySelectorAll('[data-background-choice]').forEach(item => item.setAttribute('aria-pressed', String(item === button))); + }); + } + for (const button of document.querySelectorAll('[data-size]')) { + button.addEventListener('click', () => { + document.documentElement.style.setProperty('--icon-size', `${button.dataset.size}px`); + document.querySelectorAll('[data-size]').forEach(item => item.setAttribute('aria-pressed', String(item === button))); + }); + } + filter(); +})(); +""" + + +def options(assets: list[dict], key: str, labels: dict[str, str]) -> str: + values = dict.fromkeys(asset.get(key, "unknown") for asset in assets) + return "".join(f'' for value in values) + + +def build() -> tuple[int, int]: + assets = read_assets() + ready = sum(asset["ready"] for asset in assets) + pending = len(assets) - ready + content = f''' + +Saumwacht · Assetgalerie · Phase 3 + + +

Saumwacht / Werkstatt / Phase 03

+

Die Welt nimmt Form an.

Einheiten, Ressourcen und Oberflächen in einer gemeinsamen Bildsprache. Native PNG-Originale vergleichen, Details prüfen und Prompts nachlesen.

+
Geplant
{len(assets)}
Vorhanden
{ready}
Ausstehend
{pending}
+
+ + + +
+
Hintergrund zur Alpha-Prüfung
+
Icongröße
+

Karten und UI behalten ihr Seitenverhältnis. Ein Klick aufs Bild öffnet das Original.

+ +

{len(assets)} Assets · {ready} vorhanden · {pending} ausstehend

+ +
+

Offline-Galerie · Bilder unverändert aus den nativen PNG-Masters.

Aktualisieren: python3 tools/build_asset_gallery.py

+ +''' + OUTPUT.write_text(content, encoding="utf-8") + return len(assets), ready + + +if __name__ == "__main__": + total, available = build() + print(f"Galerie: {OUTPUT}\n{total} Assets: {available} vorhanden, {total - available} ausstehend.") diff --git a/tools/build_demo.py b/tools/build_demo.py new file mode 100644 index 0000000..8c98ccc --- /dev/null +++ b/tools/build_demo.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +"""Export both release programs and package them with instructions and licenses.""" +from pathlib import Path +import argparse, configparser, fnmatch, hashlib, json, re, shutil, subprocess, zipfile + +PROJECT = Path(__file__).resolve().parents[1] +DIST = PROJECT.parent / 'dist' +VERSION = '0.15.0' +SKELETAL_RELEASE_MODELS = { + 'w04': ('assets/phase11_manifest.json', 'res://assets/characters/ringborke.glb'), + 'worker': ('assets/phase12_manifest.json', 'res://assets/characters/arbeiter.glb'), + 'g04': ('assets/phase15_manifest.json', 'res://assets/characters/basaltbastion.glb'), + 'w10': ('assets/phase16_manifest.json', 'res://assets/characters/quellgeflecht.glb'), + 'g05': ('assets/phase18_manifest.json', 'res://assets/characters/funkenlanze.glb'), + 'g06': ('assets/phase19_manifest.json', 'res://assets/characters/glasballiste.glb'), +} +INTRO = '''SAUMWACHT – DIE GRÜNE KLUFT · DEMO {version} + +START +{start} +Godot und Blender werden zum Spielen nicht benötigt. +Die Spieldaten sind in das Programm eingebettet. Das ganze ZIP zunächst entpacken. + +HAUPTMENÜ 0.15 +Neuer Spieleinstieg vor einer 3D-Bühne an der Grünen Kluft: Glutpakt und +Wurzelbund stehen mit echten Spielmodellen an ihren Saumkernen. +Bundwahl über gestaltete Karten mit Emblem und Spielweise; Partielänge, +Rivalenbund, KI-Stufe und Bauzeit bleiben wählbar (letztere unter +Weitere Einstellungen). Optionen: Bewegung reduzieren schaltet Kamerafahrten, +Partikel und Überblendungen im Menü ab. Das Bild füllt jetzt auch 16:9. + +GRAFIK UND MENÜ +Cineastische Beleuchtung, Farbabstimmung, HUD und Optionsdialog. +Der Funkenleser zeigt Werkzeugkontakt, Aufnehmen, Einfüllen und Rückkehr. +Die Ringborke behält ihren Körperbau und ihre neun Bewegungen. +Basaltbastion und Quellgeflecht besitzen ebenfalls gewichtete Skelette +mit je neun Bewegungen für Gang, Angriff, Fähigkeit, Treffer und Tod. +Der Saumkern reagiert auf Aktivierung und Schaden. + +ANIMATIONEN 0.14 +Die Schutzhaltung der Skelettwächter folgt ihrer ausgelösten Fähigkeit. +Eine empfangene Heilung löst beim Empfänger keine eigene Fähigkeitsbewegung aus. +Arbeiter melden den Werkzeugkontakt genau einmal pro Schlag. +Dünne Blätter werden von beiden Seiten dargestellt. + +GRAFIKUPDATE +Die grüne Kluft: bewachsene Ruinen, modellierte Felswände, Brücken und Wasser. +Überarbeitete Wächter, Arbeiter und Kristalle; native 4K-Holzmaterialien. +Das Baumenü klappt während des Kampfes ein und öffnet sich zur nächsten Bauphase. + +ERSTE PARTIE +Neue Partie öffnet die Bundwahl: Wurzelbund oder Glutpakt und die Partielänge. +Rivalenbund, KI-Stufe und Bauzeit stehen unter Weitere Einstellungen. +Partie beginnen und dann Startformation klicken: 185 Gold beim Wurzelbund, +180 Gold beim Glutpakt. Tank und Nahkämpfer stehen vorn, der Schütze dahinter. +Standardmäßig bleibt die Bauphase offen, bis du Kampf starten / Leertaste drückst. +Auch die Abrechnung wartet auf dich. Das Zeitlimit ist im Menü zuschaltbar. + +Die Wurzelbund-Heiler brauchen verwundete Verbündete in 4–4,5 m Reichweite. +Wächter werden nach dem Kampf wiederhergestellt. Gold kauft Wächter und Arbeiter. +Jeder Arbeiter liefert 10 Funken pro Welle; neue Arbeiter erst ab der nächsten. +Ab Welle 3 kannst du Funken für Söldner ausgeben. Diese greifen den Rivalen an +und erhöhen dauerhaft dein Gold-Einkommen ab der nächsten Abrechnung. +Mit C oder Basis ansehen siehst du Arbeiter und Kristall, mit C kehrst du zurück. +Schütze deinen Kristall: durchgebrochene Gegner verursachen dort Schaden. +Die Expedition hat 20 Wellen und vier Bosse, die Kurzpartie acht Wellen und zwei. +Ein zerstörter Kern beendet das Duell früher. Nach der letzten Welle entscheidet +der höhere Kern-HP-Wert. Bei Gleichstand ist die Partie unentschieden. + +STEUERUNG +1–5: Wächter wählen. Linksklick: Bauen / Auswählen. Shift + Klick: mehrfach bauen. +Rechtsklick / Esc: Bauauftrag abbrechen. Leertaste: Bereit / nächste Welle. +P: Pause. Tab: Front wechseln. C: Arbeiter & Kristall. Mausrad: Zoom. +Q / E: Kamera drehen. Mittlere Maustaste ziehen: Kamera verschieben. +R: Kamera zurücksetzen. F1: Optionen und Hilfe. M: Ton stumm. F11: Vollbild. +V: 3D-Modelle groß ansehen, auswählen, drehen und Bewegungen abspielen. +Das Optionsmenü pausiert die Partie. Lautstärke, Stummschaltung, +Kamerafolge, Vollbild und Bewegung reduzieren werden lokal gespeichert. +Kein Spielstandspeichern. + +SYSTEM UND PRÜFUNG +64-Bit-System mit Vulkan-fähiger Grafik und aktuellem Grafiktreiber. +Die Standarddarstellung nutzt Forward+ mit Umgebungsverdeckung und Glühen. +Bei Start- oder Grafikproblemen: Kompatibilitaet.bat (Windows) bzw. +./Kompatibilitaet.sh (Linux) startet mit OpenGL 3.3 ohne diese Lichteffekte. +Linux: mit Godot 4.7.2, NVIDIA RTX 5060 Ti unter Fedora gestartet und geprüft. +Windows: x86-64-Release für Windows 10/11; kein echter Windows-Lauf durchgeführt. +Das eingebettete Windows-Spieldatenpaket wurde unter Linux in Kurzpartie und vollständiger Expedition geprüft. +Die EXE ist nicht signiert. Keine Installation, Online-Anmeldung oder Netzwerkpartie. + +CREDITS +Spiel, Fraktionsdesigns und prozedurale 3D-Modelle entstanden für dieses Projekt. +Stein-Albedo: generiert mit dem eingebauten Bildwerkzeug. Holzmaterial: native +4096-Pixel-Bakes aus eigenen periodischen Blender-Materialien. +Schriften: Cantarell, Cinzel und Alegreya, jeweils SIL Open Font License 1.1 +(siehe licenses/OFL-Cantarell.txt, OFL-Cinzel.txt, OFL-Alegreya.txt). +Embleme und Menü-Diorama: eigene Vektorgrafiken bzw. prozedurale Blender-Szene. +Icons: generierte Projektillustrationen. Soundeffekte: eigene synthetische Klänge, +keine fremden Samples. Zwanzig spielbare Wächter und zehn Wellengegner besitzen +modellierte Panzer, Borke, Wurzeln, Gelenke und Ornamente. Arbeiter und Kristalle +wurden ebenfalls neu aufgebaut. Ringborke, Funkenleser, Basaltbastion, +Quellgeflecht, Funkenlanze und Glasballiste nutzen gewichtete Skelette; +die anderen Figuren verwenden weiterhin starre Gelenke. +Engine: Godot, https://godotengine.org – MIT-Lizenz; Lizenztexte im Ordner licenses. +''' + + +def check_release_inputs(project=PROJECT): + """Fail before export if versions or explicitly packaged runtime data diverge.""" + problems = [] + version = re.search(r'^config/version="([^"]+)"$', + (project/'project.godot').read_text(), re.MULTILINE) + if not version or version[1] != VERSION: + problems.append(f'project.godot muss config/version="{VERSION}" enthalten.') + # Discover every literal manifest reference in runtime code, including future phases. + manifests = {'assets/audio/manifest.json', 'assets/icons/manifest.json'} + for script in (project/'scripts').rglob('*.gd'): + manifests.update(re.findall(r'res://(assets/[^"\s]+manifest\.json)', script.read_text())) + manifests.update(path for path, _ in SKELETAL_RELEASE_MODELS.values()) + records = {} + for path in sorted(manifests): + try: + document = json.loads((project/path).read_text()) + if not isinstance(document, dict): + raise ValueError('JSON-Objekt erwartet') + assets = document.get('assets', []) + if not isinstance(assets, list) or any(not isinstance(asset, dict) for asset in assets): + raise ValueError('assets muss eine Liste von Objekten sein') + records[path] = document + for asset in assets: + resource = asset.get('resource_path', '') + if not isinstance(resource, str) or not resource.startswith('res://') or not (project/resource[6:]).is_file(): + problems.append(f'{path}: fehlende Ressource {resource!r}.') + except (OSError, ValueError, AttributeError, TypeError) as error: + problems.append(f'{path}: ungültiges oder fehlendes Manifest ({error}).') + for asset_id, (manifest, resource) in SKELETAL_RELEASE_MODELS.items(): + entries = records.get(manifest, {}).get('assets', []) + matches = [entry for entry in entries if isinstance(entry, dict) and entry.get('id') == asset_id] + if len(matches) != 1 or matches[0].get('resource_path') != resource or not matches[0].get('skeletal'): + problems.append(f'{manifest}: aktuelles Skelettmodell {asset_id} fehlt.') + continue + model = project/resource[6:] + if model.is_file() and hashlib.sha256(model.read_bytes()).hexdigest() != matches[0].get('sha256'): + problems.append(f'{manifest}: SHA-256 für {asset_id} stimmt nicht mit dem GLB überein.') + presets = configparser.ConfigParser(interpolation=None) + presets.read(project/'export_presets.cfg') + for index, name in enumerate(('Linux', 'Windows')): + section = f'preset.{index}' + if section not in presets or section+'.options' not in presets: + problems.append(f'Export-Preset {name} fehlt.') + continue + preset = presets[section] + if json.loads(preset.get('name', '""')) != name: + problems.append(f'{section}: Name muss {name} sein.') + if json.loads(preset.get('export_filter', '""')) != 'all_resources': + problems.append(f'{name}: Dynamisch geladene Ressourcen benötigen export_filter="all_resources".') + included = {item.strip() for item in json.loads(preset.get('include_filter', '""')).split(',')} + excluded = [item.strip() for item in json.loads(preset.get('exclude_filter', '""')).split(',') if item.strip()] + for path in sorted(manifests): + if path not in included or any(fnmatch.fnmatchcase(path, pattern) for pattern in excluded): + problems.append(f'{name}: Laufzeitmanifest {path} wird nicht explizit exportiert.') + for asset_id, (_, resource) in SKELETAL_RELEASE_MODELS.items(): + if any(fnmatch.fnmatchcase(resource[6:], pattern) for pattern in excluded): + problems.append(f'{name}: Skelettmodell {asset_id} ist vom Export ausgeschlossen.') + options = presets[section+'.options'] + for key in ('application/file_version', 'application/product_version'): + if json.loads(options.get(key, '""')) != VERSION+'.0': + problems.append(f'{name}: {key} muss {VERSION}.0 sein.') + if problems: + raise SystemExit('Release-Prüfung fehlgeschlagen:\n- ' + '\n- '.join(problems)) + print(f'RELEASE_INPUTS_PASS: Version {VERSION}, {len(manifests)} Manifeste, {len(SKELETAL_RELEASE_MODELS)} Skelettmodelle.', flush=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--check-only', action='store_true', help='Versionen und Manifeste ohne Export prüfen.') + args = parser.parse_args() + check_release_inputs() + if args.check_only: + return + godot = shutil.which('godot') or shutil.which('godot4') + if not godot: + raise SystemExit('Godot 4.7.2 ist zum Erstellen erforderlich.') + template_dir = PROJECT/'assets-source/phase6/export-templates' + if not all((template_dir/p).exists() for p in ['linux_release.x86_64','windows_release_x86_64.exe']): + raise SystemExit('Offizielle 4.7.2-Templates fehlen. Siehe docs/phase6-builds.md.') + records=[] + for name, platform, filename in [('Linux','linux','Saumwacht.x86_64'),('Windows','windows','Saumwacht.exe')]: + out = DIST/platform + out.mkdir(parents=True,exist_ok=True) + log = DIST/(platform+'-export.log') + with log.open('w') as stream: + subprocess.run([godot,'--headless','--path',str(PROJECT),'--export-release',name],stdout=stream,stderr=subprocess.STDOUT,check=True) + exe=out/filename + if not exe.is_file() or exe.stat().st_size < 1000000: + raise RuntimeError('Fehlender oder ungültiger Export: '+str(exe)) + start='Saumwacht.exe doppelt anklicken.' if platform=='windows' else './Saumwacht.x86_64 starten (alternativ ./Spielen.sh).' + (out/'LIESMICH.txt').write_text(INTRO.format(start=start,version=VERSION),encoding='utf-8') + if platform=='linux': + exe.chmod(0o755) + launcher=out/'Spielen.sh' + launcher.write_text('#!/usr/bin/env bash\nset -e\ncd -- "$(dirname -- "${BASH_SOURCE[0]}")"\nexec ./Saumwacht.x86_64 "$@"\n') + launcher.chmod(0o755) + fallback=out/'Kompatibilitaet.sh' + fallback.write_text('#!/usr/bin/env bash\nset -e\ncd -- "$(dirname -- "${BASH_SOURCE[0]}")"\nexec ./Saumwacht.x86_64 --rendering-method gl_compatibility "$@"\n') + fallback.chmod(0o755) + else: + (out/'Kompatibilitaet.bat').write_bytes(b'@echo off\r\ncd /d "%~dp0"\r\nSaumwacht.exe --rendering-method gl_compatibility %*\r\n') + license_source=PROJECT/'assets-source/phase6/licenses' + shutil.copytree(license_source,out/'licenses',dirs_exist_ok=True) + for font_license in ('OFL-Cantarell.txt', 'OFL-Cinzel.txt', 'OFL-Alegreya.txt'): + shutil.copy2(PROJECT/'assets/fonts'/font_license, out/'licenses'/font_license) + archive=DIST/f'Saumwacht-{name}-x64-{VERSION}.zip' + with zipfile.ZipFile(archive,'w',zipfile.ZIP_DEFLATED,compresslevel=6) as z: + for file in sorted(out.rglob('*')): + if file.is_file(): + z.write(file, f'Saumwacht-{name}/'+str(file.relative_to(out))) + records.append({'platform':name,'executable':str(exe.relative_to(DIST)), 'exe_bytes':exe.stat().st_size, + 'archive':archive.name,'archive_bytes':archive.stat().st_size, + 'sha256':hashlib.sha256(archive.read_bytes()).hexdigest(), + 'exe_sha256':hashlib.sha256(exe.read_bytes()).hexdigest()}) + print(f'{name}: {archive.name} ({archive.stat().st_size/1024/1024:.1f} MiB)',flush=True) + (DIST/'build-manifest.json').write_text(json.dumps({'version':VERSION,'engine':'4.7.2.stable','builds':records},indent=2)+'\n') + (DIST/'SHA256SUMS.txt').write_text(''.join(r['sha256']+' '+r['archive']+'\n' for r in records)) + +if __name__=='__main__': + main() diff --git a/tools/build_phase4_reference_gallery.py b/tools/build_phase4_reference_gallery.py new file mode 100644 index 0000000..86de8ca --- /dev/null +++ b/tools/build_phase4_reference_gallery.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +"""Build an offline comparison index and catalog from the current export manifest.""" +from html import escape +import json +from pathlib import Path + +PROJECT = Path(__file__).resolve().parents[1] +OUT = PROJECT / 'docs/screenshots/phase4' +FACTIONS = {'glutpakt': 'Glutpakt', 'nietenkonvent': 'Nietenkonvent', + 'nebelchor': 'Nebelchor', 'wurzelbund': 'Wurzelbund', 'neutral': 'Söldner & Arbeiter'} +ROLES = {'melee': 'Nahkampf', 'tank': 'Tank', 'ranged': 'Fernkampf', + 'artillery': 'Artillerie', 'support': 'Unterstützung', 'mercenary': 'Söldner', + 'worker': 'Arbeiter', 'lane': 'Lane-Segment', 'enemy': 'Wellengegner', 'core': 'Saumkern'} + + +def main(): + assets = json.loads((PROJECT / 'assets/phase4_manifest.json').read_text())['assets'] + cards = [] + for faction, label in FACTIONS.items(): + selected = [a for a in assets if a['faction'] == faction] + for start in range(0, len(selected), 2): + pair = selected[start:start + 2] + filename = 'reference-' + pair[0]['id'] + '.png' + assert (OUT / filename).is_file(), filename + title = ' / '.join(a['id'].upper() + ' · ' + a['name'] for a in pair) + downloads = ' · '.join( + f'{a["id"].upper()}: GLB / ' + f'Blender' for a in pair) + cards.append(f'
{escape(label)}' + f'

{escape(title)}

' + f'' + f'
{downloads}
') + buttons = '' + buttons += ''.join(f'' + for key, value in FACTIONS.items()) + html = ''' +Saumwacht · Bild und Modell
Saumwacht / Grafiküberarbeitung / 16. September 2026
+

Bild und Modell.
Direkt nebeneinander.

+

Die zwanzig Glutpakt- und Wurzelbund-Figuren wurden mit hochdetaillierter Geometrie neu aufgebaut; Nietenkonvent und Nebelchor behalten ihren bisherigen Detailgrad. Jeder Vergleich zeigt die unveränderte Illustration neben dem aktuellen Modell aus Godot. Klicke auf ein Bild, um es in voller Größe zu öffnen.

+

Die neuen Glutpakt-Modelle besitzen modellierte Gelenke, Panzerplatten, Metallkanten, Finger und Feuerkammern. Die Illustrationen dienen als Stilvorlage; die Figuren sind eigenständige 3D-Umsetzungen. Der Wurzelbund ergänzt geflochtene Wurzeln, Borkenplatten, Blattadern, Pilzkelche und Heilbecken.

+
23 Vergleichsbilder · 46 Figuren
+''' + '\n'.join(cards) + ''' +

Die Vorschauen passen die Figuren auf eine gemeinsame Bühne ein; sie vergleichen keine Weltmaßstäbe. Lane, Teamkerne und die zehn Wellengegner wurden ebenfalls überarbeitet. +Wellengegner ansehen · Umgebung ansehen · 3D-Werkstatt ansehen

+''' + (OUT / 'reference-gallery.html').write_text(html, encoding='utf-8') + + catalog = ['# Saumwacht · Modellkatalog', '', + 'Stand: 17. September 2026. Zwanzig Glutpakt- und Wurzelbund-Figuren, zehn Wellengegner, Arbeiter und Kristalle wurden neu aufgebaut; Söldner und Lane erhielten zusätzliche Details. Die 59 Einträge stammen aus `assets/phase4_manifest.json`.', '', + 'Maße in Metern: **B = X, H = Y, T = Z** in Godot, auf zwei Nachkommastellen gerundet. ' + 'GLBs sind über die IDs verlinkt; native Quellen liegen in `blend/.blend`. ' + '[Anleitung](README.md) · [Bildvergleiche](../../docs/screenshots/phase4/reference-gallery.html)', '', + '| ID / GLB | Modell | Fraktion | Rolle | Upgrade | Dreiecke | B (m) | H (m) | T (m) |', + '| --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: |'] + for a in assets: + b = a['bounds_godot'] + dims = [hi-lo for hi, lo in zip(b['max'], b['min'])] + faction = FACTIONS.get(a['faction'], 'Risskreaturen' if a['faction']=='rift' else 'Umgebung') + upgrade = 'Ja' if a.get('upgraded', a.get('upgrade', False)) else 'Nein' + catalog.append(f'| [{a["id"]}](../../assets/models/{a["file"]}) | {a["name"]} | {faction} | ' + f'{ROLES[a["role"]]} | {upgrade} | {a["triangles"]} | ' + ' | '.join(f'{d:.2f}' for d in dims) + ' |') + (PROJECT / 'assets-source/phase4/catalog.md').write_text('\n'.join(catalog)+'\n', encoding='utf-8') + print('REFERENCE_GALLERY_PASS: 23 comparison sheets, 46 characters; catalog 59 models') + + +if __name__ == '__main__': + main() diff --git a/tools/build_standalone_model_scripts.py b/tools/build_standalone_model_scripts.py new file mode 100644 index 0000000..7ff5411 --- /dev/null +++ b/tools/build_standalone_model_scripts.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Bundle the modular bpy sources into nine genuinely self-contained scripts. + +No Blender dependency for this build step. Source comments and shape functions +are preserved; only imports of our own modules and the batch dispatcher vanish. +""" +import ast +from pathlib import Path +from pprint import pformat +import sys + +PROJECT = Path(__file__).resolve().parents[1] +SOURCE = PROJECT / 'assets-source' / 'phase4' +MODULES = SOURCE / 'blender' +OUTPUT = SOURCE / 'standalone' +sys.path.insert(0, str(MODULES)) +from catalog import specs + +ENTRIES = [ + ('melee', 'frontline', 'g01', 'Nahkämpfer'), + ('tank', 'frontline', 'g03', 'Tank'), + ('ranged', 'backline', 'g05', 'Fernkämpfer'), + ('artillery', 'backline', 'g07', 'Flächenkämpfer'), + ('support', 'backline', 'g09', 'Unterstützer'), + ('mercenary', 'environment', 's01', 'Söldner'), + ('worker', 'environment', 'worker', 'Funkenleser'), + ('lane', 'environment', 'map_lane_segment', 'Lane-Segment'), + ('core', 'environment', 'core_team0', 'Teamkerne'), +] + + +def bundled_source(filename, skip_functions=()): + source = (MODULES / filename).read_text(encoding='utf-8') + lines = source.splitlines(keepends=True) + skipped = set() + for node in ast.parse(source).body: + own_import = isinstance(node, ast.ImportFrom) and (node.module in ('common', 'catalog') or node.module.startswith('reference_')) + omitted_function = isinstance(node, ast.FunctionDef) and node.name in skip_functions + docstring = isinstance(node, ast.Expr) and isinstance(node.value, ast.Constant) and isinstance(node.value.value, str) + if own_import or omitted_function or docstring: + skipped.update(range(node.lineno - 1, node.end_lineno)) + return ''.join(line for i, line in enumerate(lines) if i not in skipped).strip() + + +CONFIG = ''' +from pathlib import Path +import sys +import bpy + +# === ANPASSBARE PARAMETER ================================================ +ASSET_ID = {asset_id!r} # Verfügbare IDs stehen unmittelbar unter diesem Block. +EXPORT_DIR = None # Optional: r"C:/Spiel/assets/models" oder "/home/.../models". +BLEND_DIR = None # Optionaler Ordner für die bearbeitbare .blend-Datei. +HEIGHT = None # None = Katalogmaß; sonst Zielhöhe in Metern, z. B. 1.5. +PALETTE_OVERRIDES = {{}} # Beispiel: {{'accent': 'D9A441'}}; RGB-Hex ohne Alpha. +KEEP_SCENE = True # Generiertes Modell nach Ausführung in Blender anzeigen. +# Formteile und Proportionen sind weiter unten als kleine Funktionen editierbar. +# Bei großen Waffen begrenzt der Zell-Footprint ggf. die endgültige Höhe. +# Dieses Skript braucht nur Blender/bpy, keine Projektmodule oder JSON-Dateien. + +def _script_directory(): + candidate = globals().get('__file__', '') + if candidate and Path(candidate).is_file(): + return Path(candidate).resolve().parent + text = getattr(getattr(bpy.context, 'space_data', None), 'text', None) + if text is not None and text.filepath: + return Path(bpy.path.abspath(text.filepath)).resolve().parent + return Path.cwd() + +SCRIPT_DIR = _script_directory() +PROJECT = next((p for p in [SCRIPT_DIR, *SCRIPT_DIR.parents] + if (p / 'project.godot').is_file()), SCRIPT_DIR) +IN_PROJECT = (PROJECT / 'project.godot').is_file() +SOURCE = PROJECT / 'assets-source' / 'phase4' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-source' +DEFAULT_EXPORT_DIR = PROJECT / 'assets' / 'models' if IN_PROJECT else SCRIPT_DIR / 'saumwacht-export' +DEFAULT_BLEND_DIR = SOURCE / 'blend' +''' + +MAIN = ''' + +def main(): + # CLI-Optionen sind optional; im Blender-Scripting-Tab genügt "Run Script". + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--id', default=ASSET_ID) + parser.add_argument('--export-dir', default=EXPORT_DIR) + parser.add_argument('--blend-dir', default=BLEND_DIR) + parser.add_argument('--height', type=float, default=HEIGHT) + parser.add_argument('--no-keep-scene', action='store_true') + args = parser.parse_args(sys.argv[sys.argv.index('--') + 1:] if '--' in sys.argv else []) + build_one(args.id, export_dir=args.export_dir, blend_dir=args.blend_dir, + height=args.height, palette_overrides=PALETTE_OVERRIDES, + keep_scene=KEEP_SCENE and not args.no_keep_scene) + print('STANDALONE_PASS:', args.id) + + +if __name__ == '__main__': + main() +''' + + +def main(): + OUTPUT.mkdir(parents=True, exist_ok=True) + for role, module, asset_id, label in ENTRIES: + selected = [s for s in specs() if s['role'] == role] + header = f'"""Saumwacht · {label} · eigenständiges Blender-Python-Skript.\n\n' + header += 'In Blender: Scripting > Text > Open > diese Datei > Run Script.\n' + header += 'Vorhandene Szenen bleiben erhalten. GLB und .blend werden automatisch exportiert.\n' + header += 'Generiert aus den modularen Quellen mit tools/build_standalone_model_scripts.py.\n' + header += 'Getestet mit Blender 5.2.1; verwendet grundlegende bpy/glTF-APIs.\n"""\n' + data = '\n# === VERFÜGBARE VARIANTEN ===============================================\n' + data += 'ASSET_SPECS = ' + pformat(selected, width=105, sort_dicts=False) + '\n' + data += '\ndef get_spec(asset_id):\n for spec in ASSET_SPECS:\n if spec["id"] == asset_id:\n return dict(spec)\n raise ValueError("Unbekannte ID für dieses Skript: " + asset_id)\n' + dispatcher = '\ndef _builder(role):\n return globals()["build_" + role]\n' + body = '\n\n'.join([ + bundled_source('common.py'), bundled_source('reference_geometry.py'), + bundled_source('reference_high_detail.py'), bundled_source('reference_living_detail.py'), bundled_source('reference_sculpt_detail.py'), + bundled_source('reference_glutpakt.py'), bundled_source('reference_nebelchor.py'), + bundled_source('reference_nietenkonvent.py'), bundled_source('reference_wurzelbund.py'), + bundled_source('reference_neutral.py'), + bundled_source(module + '.py'), dispatcher, + bundled_source('pipeline.py', ('_builder', 'write_manifest')), + ]) + content = header + CONFIG.format(asset_id=asset_id) + data + '\n' + body + MAIN + path = OUTPUT / ('create_' + role + '.py') + compile(content, str(path), 'exec') + path.write_text(content, encoding='utf-8') + print(path.name, '·', len(selected), 'Varianten') + + +if __name__ == '__main__': + main() diff --git a/tools/compare_stage.gd b/tools/compare_stage.gd new file mode 100644 index 0000000..a3b138f --- /dev/null +++ b/tools/compare_stage.gd @@ -0,0 +1,211 @@ +extends Node3D +## Godot/Unreal comparison stage: identical portable assets, cameras and lighting. +## Captures close-up + game-camera stills, a walk cycle, and 1/30/90 load measurements. + +const CAPTURES := "res://docs/screenshots/compare" +var viewport: SubViewport +var stage: Node3D +var camera: Camera3D +var figures: Array[Node3D] = [] +var results: Array = [] + +func _ready() -> void: + call_deferred("run") + +func _load_glb(path: String) -> Node3D: + var packed := load(path) as PackedScene + if packed == null: + push_error("Missing compare asset: " + path) + return Node3D.new() + return packed.instantiate() as Node3D + +func _shot(name: String) -> void: + for n: int in range(8): + await get_tree().process_frame + await RenderingServer.frame_post_draw + viewport.get_texture().get_image().save_png(CAPTURES + "/" + name + ".png") + print("SHOT: ", name) + +func _aim(pos: Vector3, target: Vector3, size: float) -> void: + camera.size = size + camera.position = pos + camera.look_at(target, Vector3.UP) + await get_tree().process_frame + await get_tree().process_frame + +func run() -> void: + Soundscape.enabled = false + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + get_window().size = Vector2i(960, 540) + viewport = SubViewport.new() + viewport.own_world_3d = true + viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS + viewport.msaa_3d = Viewport.MSAA_4X + viewport.size = Vector2i(1920, 1080) + add_child(viewport) + stage = Node3D.new() + viewport.add_child(stage) + var display := TextureRect.new() + display.texture = viewport.get_texture() + display.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + display.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + add_child(display) + + var env := WorldEnvironment.new() + env.environment = Environment.new() + preload("res://scripts/presentation/lighting.gd").configure(env.environment, true) + stage.add_child(env) + var light := DirectionalLight3D.new() + light.rotation_degrees = Vector3(-48, -36, 0) + light.light_color = Color("ffd4a0") + light.light_energy = 1.7 + light.shadow_enabled = true + stage.add_child(light) + var fill := DirectionalLight3D.new() + fill.rotation_degrees = Vector3(-35, 150, 0) + fill.light_color = Color("a8c4e8") + fill.light_energy = .55 + stage.add_child(fill) + + # Solid unshaded stage floor so studio light cannot blow it out. + var floor := MeshInstance3D.new() + var plane := PlaneMesh.new() + plane.size = Vector2(24, 24) + floor.mesh = plane + var floor_mat := StandardMaterial3D.new() + floor_mat.albedo_color = Color("243038") + floor_mat.roughness = 1.0 + floor_mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED + floor.material_override = floor_mat + stage.add_child(floor) + # Arena tile as a modest platform under the figures. + var tile: Node3D = _load_glb("res://assets/compare/compare-arena-tile.glb") + tile.position = Vector3(0, .01, .35) + tile.scale = Vector3(0.85, .35, 0.7) + stage.add_child(tile) + + var rock: Node3D = _load_glb("res://assets/compare/compare-rock.glb") + rock.position = Vector3(-2.8, 0, -1.0) + rock.rotation.y = .45 + rock.scale = Vector3.ONE * 1.0 + stage.add_child(rock) + var tree: Node3D = _load_glb("res://assets/compare/compare-tree.glb") + tree.position = Vector3(3.0, 0, -1.5) + tree.rotation.y = -.35 + tree.scale = Vector3.ONE * .9 + stage.add_child(tree) + + var ring: Node3D = AssetLibrary.instantiate_fighter("w04") + ring.position = Vector3(-0.6, 0, 0.55) + ring.rotation.y = .2 + stage.add_child(ring) + figures.append(ring) + var worker: Node3D = AssetLibrary.instantiate_fighter("worker") + worker.position = Vector3(0.9, 0, 0.7) + worker.rotation.y = -.45 + stage.add_child(worker) + figures.append(worker) + var core: Node3D = AssetLibrary.instantiate_fighter("core_team0") + core.position = Vector3(0.1, 0, -1.8) + stage.add_child(core) + + camera = Camera3D.new() + camera.projection = Camera3D.PROJECTION_ORTHOGONAL + camera.size = 2.4 + stage.add_child(camera) + await get_tree().process_frame + + # 1) Close-up of pattern figure + worker. + await _aim(Vector3(1.6, 1.6, 2.6), Vector3(0.1, 1.0, 0.2), 2.4) + print("CAM closeup size=", camera.size, " pos=", camera.position) + await _shot("closeup") + # 2) Game camera: high and wide so rock, tree, core and figures all read. + await _aim(Vector3(2.0, 14.0, 12.5), Vector3(0, 0.4, -0.2), 10.0) + print("CAM game size=", camera.size, " pos=", camera.position) + await _shot("game-camera") + # 3) Movement pass on the game camera. + for i in range(30): + var t: float = i / 10.0 + if ring.has_method("preview"): + ring.preview("walk", fmod(t, ring.clip_length("walk"))) + if worker.has_method("update_work"): + worker.update_work(1.0 / 10.0, 0.0) + await get_tree().process_frame + if i in [0, 12, 24]: + await RenderingServer.frame_post_draw + viewport.get_texture().get_image().save_png(CAPTURES + "/move-%02d.png" % i) + print("SHOT: move-", i) + await _shot("move-end") + + # Load measurements 1 / 30 / 90 at 1080p and 1440p. + for resolution: Vector2i in [Vector2i(1920, 1080), Vector2i(2560, 1440)]: + viewport.size = resolution + for count: int in [1, 30, 90]: + for figure: Node3D in figures: + if is_instance_valid(figure): + figure.free() + figures.clear() + var columns: int = ceili(sqrt(count)) + for i: int in range(count): + var figure: Node3D = AssetLibrary.instantiate_fighter("w04" if i % 2 == 0 else "worker") + figure.position = Vector3((i % columns - columns * .5) * 2.2, 0, (i / float(columns) - columns * .5) * 2.2 + 2.5) + stage.add_child(figure) + figures.append(figure) + await _aim(Vector3(6, 16, 20), Vector3(0, 0.8, 1.5), maxf(4, columns * 2.5)) + var times: Array[float] = [] + var started: int = Time.get_ticks_usec() + var previous: int = started + while Time.get_ticks_usec() - started < 8000000: + var elapsed: float = (Time.get_ticks_usec() - started) / 1000000.0 + for i: int in range(figures.size()): + var figure: Node3D = figures[i] + if figure.has_method("preview"): + figure.preview("walk", fmod(elapsed + i * .05, 1.4)) + elif figure.has_method("update_work"): + figure.update_work(1.0 / 60.0, i * .1) + await get_tree().process_frame + var now: int = Time.get_ticks_usec() + if elapsed > 2: + times.append((now - previous) / 1000.0) + previous = now + var total: float = 0 + for t: float in times: + total += t + times.sort() + var record := { + "resolution": str(resolution), + "instances": count, + "mean_frame_ms": total / maxf(1, times.size()), + "p95_frame_ms": times[int(times.size() * .95)] if not times.is_empty() else 0.0, + "fps": 1000.0 / maxf(0.01, total / maxf(1, times.size())), + "draw_calls": Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME), + "video_memory_bytes": Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED), + } + results.append(record) + print("COMPARE_BENCH: ", record) + + var report := { + "engine": "Godot " + Engine.get_version_info().get("string", ""), + "device": RenderingServer.get_video_adapter_name(), + "renderer": RenderingServer.get_current_rendering_method(), + "vsync": false, + "msaa": "4x", + "warmup_seconds": 2, + "sample_seconds": 6, + "scope": "Comparison stage: pattern figure, worker, core, rock, tree, arena tile. Not a full match.", + "camera": { + "projection": "orthogonal", + "closeup": {"position": [1.4, 1.5, 2.4], "look_at": [0.1, 0.95, 0.2], "size": 2.4}, + "game": {"position": [1.5, 10.5, 9.5], "look_at": [0, 0.5, 0], "size": 7.0, "yaw": 0.2}, + }, + "lighting": { + "key": {"rotation_degrees": [-48, -36, 0], "color": "#ffd4a0", "energy": 1.7}, + "fill": {"rotation_degrees": [-35, 150, 0], "color": "#a8c4e8", "energy": 0.55}, + "tonemap": "ACES", + }, + "captures": ["closeup", "game-camera", "move-00", "move-12", "move-24", "move-end"], + "results": results, + } + FileAccess.open("res://docs/compare-godot.json", FileAccess.WRITE).store_string(JSON.stringify(report, "\t")) + print("COMPARE_STAGE_PASS") + await Soundscape.quit_game() diff --git a/tools/compare_stage.gd.uid b/tools/compare_stage.gd.uid new file mode 100644 index 0000000..1b8cf5a --- /dev/null +++ b/tools/compare_stage.gd.uid @@ -0,0 +1 @@ +uid://d1rnxc5j47un2 diff --git a/tools/compare_stage.tscn b/tools/compare_stage.tscn new file mode 100644 index 0000000..d5f6675 --- /dev/null +++ b/tools/compare_stage.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8comparestage"] + +[ext_resource type="Script" path="res://tools/compare_stage.gd" id="1"] + +[node name="CompareStage" type="Node3D"] +script = ExtResource("1") diff --git a/tools/funken_review.gd b/tools/funken_review.gd new file mode 100644 index 0000000..ac7826f --- /dev/null +++ b/tools/funken_review.gd @@ -0,0 +1,38 @@ +extends Node +## Capture Funkenlanze review stills. Asserts the inspector shows g05 before each shot. +var main: Node3D +var captures := "res://docs/screenshots/phase18" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") +func run() -> void: + get_window().size = Vector2i(1600, 1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("g05") + print("FUNKEN_MODEL: ", main.hud.model_inspector.model_id, " caption=", main.hud.model_inspector._caption.text, " path=", AssetLibrary._models.get("g05", {}).get("resource_path"), " tris=", AssetLibrary._models.get("g05", {}).get("triangles")) + if main.hud.model_inspector.model_id != "g05": + printerr("FUNKEN_REVIEW_FAIL: inspector shows ", main.hud.model_inspector.model_id, " instead of g05") + await Soundscape.quit_game(1) + return + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + studio._turntable.rotation.y = -.15 + await shot("funken-front") + studio._turntable.rotation.y = PI + await shot("funken-back") + studio._turntable.rotation.y = -.15 + for clip: String in ["walk", "attack_a", "ability", "death"]: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip: + studio._clip_selector.select(i) + studio._clip_time = .55 if clip == "walk" else (.9 if clip == "attack_a" else (1.0 if clip == "ability" else 1.2)) + await shot("pose-" + clip) + print("FUNKEN_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/funken_review.gd.uid b/tools/funken_review.gd.uid new file mode 100644 index 0000000..7790010 --- /dev/null +++ b/tools/funken_review.gd.uid @@ -0,0 +1 @@ +uid://812drqx728l5 diff --git a/tools/funken_review.tscn b/tools/funken_review.tscn new file mode 100644 index 0000000..3e9e53d --- /dev/null +++ b/tools/funken_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8funkenreview"] + +[ext_resource type="Script" path="res://tools/funken_review.gd" id="1"] + +[node name="FunkenReview" type="Node"] +script = ExtResource("1") diff --git a/tools/generate_audio.py b/tools/generate_audio.py new file mode 100644 index 0000000..4cf05c4 --- /dev/null +++ b/tools/generate_audio.py @@ -0,0 +1,46 @@ +"""Original synthesized SFX. No samples or third-party audio. Reproducible PCM.""" +from pathlib import Path +import math, random, struct, wave, json +ROOT = Path(__file__).resolve().parents[1] +OUT = ROOT / 'assets/audio' +RATE = 24000 + +def create(name, duration, tones=(), noise=0.0, decay=8, sweep=0.0): + rng = random.Random(name) + values = [] + low = 0.0 + for i in range(round(RATE * duration)): + t = i / RATE + env = min(1, t/.006) * min(1, (duration-t)/.035) * math.exp(-decay*t/duration) + low = .72*low + .28*rng.uniform(-1,1) + sample = noise * low + for hz, weight, delay in tones: + tt = max(0,t-delay) + if t >= delay: + sample += weight * math.sin(2*math.pi*(hz*tt+sweep*tt*tt)) * math.exp(-2*tt/duration) + values.append(sample*env) + peak = max(abs(x) for x in values) or 1 + pcm = b''.join(struct.pack(' void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(6): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") + print("GLASS_FIELD_SHOT: ", name, " phase=", GameState.phase_name(), " size=", main.camera.size) +func upgrade_to_glass(cell: Vector2i) -> bool: + if not EconomyManager.apply_command(0, {"type": "build", "type_id": "g05", "cell": cell}).ok and cell != Vector2i(2, 4): + return false + for entry: Dictionary in EconomyManager.get_team(0).roster: + if entry.cell == cell and entry.type_id == "g05": + return EconomyManager.apply_command(0, {"type": "upgrade", "uid": entry.uid}).ok + return false +func run() -> void: + get_window().size = Vector2i(1600, 960) + Soundscape.enabled = false + GameState.select_faction(0, "glutpakt") + GameState.select_faction(1, "wurzelbund") + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + await get_tree().create_timer(.8).timeout + main.hud._overlay_action.pressed.emit() + await get_tree().process_frame + main.hud._starter_button.pressed.emit() + # Presentation capture only: extra gold for two upgrades, no balance values change. + EconomyManager.teams[0].gold += 500 + var ok: bool = upgrade_to_glass(Vector2i(2, 4)) and upgrade_to_glass(Vector2i(4, 4)) + var glass: int = EconomyManager.get_team(0).roster.filter(func(e: Dictionary) -> bool: return e.type_id == "g06").size() + print("GLASS_FIELD_ROSTER: ", glass, " Glasballisten") + if not ok or glass != 2: + printerr("GLASS_FIELD_FAIL: upgrade to g06 failed") + await Soundscape.quit_game(1) + return + await get_tree().create_timer(.6).timeout + await shot("field-build") + # Closer game-camera framing, same angle and projection as play. + main._manual_camera = true + main._focus = Vector3(-9.0, 0, 2.0) + main.camera.size = 13.0 + main._place_camera() + await shot("field-build-close") + main._manual_camera = false + WaveManager.set_physics_process(true) + main.hud._pause_button.grab_focus() + var key := InputEventKey.new() + key.keycode = KEY_SPACE + key.pressed = true + get_viewport().push_input(key, true) + await get_tree().create_timer(4.5).timeout + await shot("field-combat") + print("GLASS_FIELD_PASS") + await Soundscape.quit_game() diff --git a/tools/glass_field_review.gd.uid b/tools/glass_field_review.gd.uid new file mode 100644 index 0000000..932666d --- /dev/null +++ b/tools/glass_field_review.gd.uid @@ -0,0 +1 @@ +uid://dd4072fvvp0dx diff --git a/tools/glass_field_review.tscn b/tools/glass_field_review.tscn new file mode 100644 index 0000000..b7841ab --- /dev/null +++ b/tools/glass_field_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/glass_field_review.gd" id="1"] + +[node name="GlassFieldReview" type="Node"] +script = ExtResource("1") diff --git a/tools/glass_review.gd b/tools/glass_review.gd new file mode 100644 index 0000000..bbbf916 --- /dev/null +++ b/tools/glass_review.gd @@ -0,0 +1,42 @@ +extends Node +## Capture Glasballiste review stills. Asserts the inspector shows g06 before each shot. +var main: Node3D +var captures := "res://docs/screenshots/phase19" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + print("GLASS_SHOT: ", name, " id=", main.hud.model_inspector.model_id, " caption=", main.hud.model_inspector._caption.text, " details=", main.hud.model_inspector._details.text) + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") +func run() -> void: + get_window().size = Vector2i(1600, 1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("g06") + print("GLASS_MODEL: ", main.hud.model_inspector.model_id, " caption=", main.hud.model_inspector._caption.text, " path=", AssetLibrary._models.get("g06", {}).get("resource_path"), " tris=", AssetLibrary._models.get("g06", {}).get("triangles")) + if main.hud.model_inspector.model_id != "g06": + printerr("GLASS_REVIEW_FAIL: inspector shows ", main.hud.model_inspector.model_id, " instead of g06") + await Soundscape.quit_game(1) + return + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + # Three-quarter views show the long bolt and bow span, as in the concept. + studio._turntable.rotation.y = -.45 + await shot("glass-front") + studio._turntable.rotation.y = PI - .45 + await shot("glass-back") + studio._turntable.rotation.y = -.45 + # Walk mid-stride, release just after contact, braced aim, full charge, collapsed. + var times: Dictionary = {"walk": .55, "attack_a": .95, "attack_b": .60, "ability": .80, "death": 2.0} + for clip: String in times: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip: + studio._clip_selector.select(i) + studio._clip_time = times[clip] + await shot("pose-" + clip) + print("GLASS_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/glass_review.gd.uid b/tools/glass_review.gd.uid new file mode 100644 index 0000000..17cae90 --- /dev/null +++ b/tools/glass_review.gd.uid @@ -0,0 +1 @@ +uid://cro14wxhvnygd diff --git a/tools/glass_review.tscn b/tools/glass_review.tscn new file mode 100644 index 0000000..da04250 --- /dev/null +++ b/tools/glass_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8glassreview"] + +[ext_resource type="Script" path="res://tools/glass_review.gd" id="1"] + +[node name="GlassReview" type="Node"] +script = ExtResource("1") diff --git a/tools/inspect_ringborke.gd b/tools/inspect_ringborke.gd new file mode 100644 index 0000000..516ec5c --- /dev/null +++ b/tools/inspect_ringborke.gd @@ -0,0 +1,12 @@ +extends SceneTree +func _initialize() -> void: + call_deferred("run") +func run() -> void: + var source: Node = load("res://assets/characters/ringborke.glb").instantiate() + root.add_child(source) + source.print_tree_pretty() + for n: Node in source.find_children("*","AnimationPlayer",true,false): + print("CLIPS: ",n.get_animation_list()) + for clip: String in n.get_animation_list():print(clip," ",n.get_animation(clip).length," tracks ",n.get_animation(clip).get_track_count()) + for n: Node in source.find_children("*","Skeleton3D",true,false):print("BONES: ",n.get_bone_count()) + quit() diff --git a/tools/inspect_ringborke.gd.uid b/tools/inspect_ringborke.gd.uid new file mode 100644 index 0000000..262c8f8 --- /dev/null +++ b/tools/inspect_ringborke.gd.uid @@ -0,0 +1 @@ +uid://d110atrqnarcn diff --git a/tools/menu_before_capture.gd b/tools/menu_before_capture.gd new file mode 100644 index 0000000..2e7ff89 --- /dev/null +++ b/tools/menu_before_capture.gd @@ -0,0 +1,34 @@ +extends Node +## Baseline captures of the phase-13 menu before phase 20A (kept for comparison). +## Run: godot --path . res://tools/menu_before_capture.tscn -- --size=1920x1080 +var main: Node3D +var captures := "res://docs/screenshots/phase20/before" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(12): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") + print("BEFORE_SHOT: ", name, " ", get_viewport().get_texture().get_size()) +func run() -> void: + var size := Vector2i(1920, 1080) + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--size="): + var parts: PackedStringArray = arg.substr(7).split("x") + size = Vector2i(int(parts[0]), int(parts[1])) + get_window().size = size + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + var tag := "%dx%d" % [size.x, size.y] + await shot("menu-" + tag) + GameState.select_faction(0, "glutpakt") + GameState.select_faction(1, "wurzelbund") + main.hud._phase_changed(GameState.phase) + await shot("menu-glutpakt-" + tag) + main.hud.toggle_settings() + await shot("options-" + tag) + main.hud.toggle_settings() + print("BEFORE_CAPTURE_PASS") + await Soundscape.quit_game() diff --git a/tools/menu_before_capture.gd.uid b/tools/menu_before_capture.gd.uid new file mode 100644 index 0000000..ddc8760 --- /dev/null +++ b/tools/menu_before_capture.gd.uid @@ -0,0 +1 @@ +uid://c54c70tr6lcd7 diff --git a/tools/menu_before_capture.tscn b/tools/menu_before_capture.tscn new file mode 100644 index 0000000..e9847c5 --- /dev/null +++ b/tools/menu_before_capture.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/menu_before_capture.gd" id="1"] + +[node name="MenuBeforeCapture" type="Node"] +script = ExtResource("1") diff --git a/tools/menu_benchmark.gd b/tools/menu_benchmark.gd new file mode 100644 index 0000000..8acf7cf --- /dev/null +++ b/tools/menu_benchmark.gd @@ -0,0 +1,83 @@ +extends Node +## Menu load time and frame cost on the current machine (no general performance claim). +## Run: godot --path . --resolution 1920x1080 res://tools/menu_benchmark.tscn -- --label=after +var main: Node3D +func _ready() -> void: + call_deferred("run") +func viewports() -> Array[RID]: + var list: Array[RID] = [get_viewport().get_viewport_rid()] + for node: Node in get_tree().root.find_children("*", "SubViewport", true, false): + if (node as SubViewport).render_target_update_mode != SubViewport.UPDATE_DISABLED: + list.append((node as SubViewport).get_viewport_rid()) + return list +func run() -> void: + var label := "run" + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--label="): + label = arg.substr(8) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + var started: int = Time.get_ticks_usec() + main = load("res://scenes/main.tscn").instantiate() + add_child(main) + var instanced: int = Time.get_ticks_usec() + await RenderingServer.frame_post_draw + var first_frame: int = Time.get_ticks_usec() + var in_game: bool = "--in-game" in OS.get_cmdline_user_args() + var stage_ready_ms: float = -1.0 + var menu: Node = main.hud.get("main_menu") + if menu != null: + while not (menu.stage.is_ready("glutpakt") and menu.stage.is_ready("wurzelbund")): + await get_tree().process_frame + stage_ready_ms = (Time.get_ticks_usec() - started) / 1000.0 + if in_game: + main.hud._overlay_action.pressed.emit() + label += "-build" + await get_tree().create_timer(1.0).timeout + for rid: RID in viewports(): + RenderingServer.viewport_set_measure_render_time(rid, true) + var warm_until: int = Time.get_ticks_msec() + 2500 + while Time.get_ticks_msec() < warm_until: + await get_tree().process_frame + var frames: Array[float] = [] + var gpu: Array[float] = [] + var cpu_render: Array[float] = [] + var draw_calls: Array[float] = [] + var last: int = Time.get_ticks_usec() + var end: int = Time.get_ticks_msec() + 6000 + while Time.get_ticks_msec() < end: + await RenderingServer.frame_post_draw + var now: int = Time.get_ticks_usec() + frames.append((now - last) / 1000.0) + last = now + var g: float = 0.0 + var c: float = 0.0 + for rid: RID in viewports(): + g += RenderingServer.viewport_get_measured_render_time_gpu(rid) + c += RenderingServer.viewport_get_measured_render_time_cpu(rid) + gpu.append(g) + cpu_render.append(c) + draw_calls.append(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME)) + frames.sort() + var mean := func(values: Array[float]) -> float: + var total: float = 0.0 + for v: float in values: total += v + return total / maxf(1, values.size()) + var report := { + "label": label, "window": get_window().size, "canvas": get_viewport().get_visible_rect().size, + "renderer": RenderingServer.get_current_rendering_method(), "gpu": RenderingServer.get_video_adapter_name(), + "driver": RenderingServer.get_video_adapter_api_version(), "engine": Engine.get_version_info().string, + "os": OS.get_name() + " " + OS.get_version(), "cpu": OS.get_processor_name(), + "instantiate_ms": (instanced - started) / 1000.0, "first_frame_ms": (first_frame - started) / 1000.0, "stage_ready_ms": stage_ready_ms, + "frames": frames.size(), "frame_ms_mean": mean.call(frames), "frame_ms_p95": frames[int(frames.size() * .95)], + "gpu_ms_mean": mean.call(gpu), "render_cpu_ms_mean": mean.call(cpu_render), + "draw_calls_mean": mean.call(draw_calls), "video_mem_mb": Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED) / 1048576.0, + "static_mem_mb": Performance.get_monitor(Performance.MEMORY_STATIC) / 1048576.0, + "vsync": "disabled", "phase": GameState.phase_name(), "viewports_measured": viewports().size()} + var path := "res://docs/phase20-logs/perf-%s-%dx%d.json" % [label, get_window().size.x, get_window().size.y] + var file := FileAccess.open(path, FileAccess.WRITE) + file.store_string(JSON.stringify(report, "\t")) + file.close() + print("MENU_BENCHMARK: ", JSON.stringify(report)) + await Soundscape.quit_game() diff --git a/tools/menu_benchmark.gd.uid b/tools/menu_benchmark.gd.uid new file mode 100644 index 0000000..a1aac0d --- /dev/null +++ b/tools/menu_benchmark.gd.uid @@ -0,0 +1 @@ +uid://bh5qe82djvqb1 diff --git a/tools/menu_benchmark.tscn b/tools/menu_benchmark.tscn new file mode 100644 index 0000000..3b3032d --- /dev/null +++ b/tools/menu_benchmark.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/menu_benchmark.gd" id="1"] + +[node name="MenuBenchmark" type="Node"] +script = ExtResource("1") diff --git a/tools/menu_reel.gd b/tools/menu_reel.gd new file mode 100644 index 0000000..f98072d --- /dev/null +++ b/tools/menu_reel.gd @@ -0,0 +1,35 @@ +extends Node +## Short recording of menu idle, transitions, Bund switch and the start into play. +## Run: godot --path . --resolution 1280x720 --fixed-fps 30 --write-movie /reel.png res://tools/menu_reel.tscn +var main: Node3D +func _ready() -> void: + call_deferred("run") +func wait(seconds: float) -> void: + await get_tree().create_timer(seconds).timeout +func run() -> void: + Soundscape.enabled = false + WaveManager.set_physics_process(false) + GameState.factions = ["wurzelbund", "glutpakt"] + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + var menu: MainMenu = main.hud.main_menu + while not (menu.stage.is_ready("glutpakt") and menu.stage.is_ready("wurzelbund")): + await get_tree().process_frame + await wait(3.0) + menu.new_game_button.pressed.emit() + await wait(2.4) + menu.faction_choice.cards[0].pressed.emit() + await wait(2.6) + menu._toggle_advanced() + await wait(1.2) + menu._toggle_advanced() + menu.faction_choice.cards[1].pressed.emit() + await wait(2.4) + menu.show_screen(MainMenu.Screen.TITLE) + await wait(2.2) + menu.new_game_button.pressed.emit() + await wait(1.6) + menu.start_button.pressed.emit() + await wait(1.4) + print("MENU_REEL_DONE") + get_tree().quit() diff --git a/tools/menu_reel.gd.uid b/tools/menu_reel.gd.uid new file mode 100644 index 0000000..21a3c2a --- /dev/null +++ b/tools/menu_reel.gd.uid @@ -0,0 +1 @@ +uid://bc1b4dv5brx60 diff --git a/tools/menu_reel.tscn b/tools/menu_reel.tscn new file mode 100644 index 0000000..0f7920f --- /dev/null +++ b/tools/menu_reel.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/menu_reel.gd" id="1"] + +[node name="MenuReel" type="Node"] +script = ExtResource("1") diff --git a/tools/menu_review.gd b/tools/menu_review.gd new file mode 100644 index 0000000..3dace95 --- /dev/null +++ b/tools/menu_review.gd @@ -0,0 +1,71 @@ +extends Node +## Phase 20A captures of the real menu: title, Bund selection, options, focus, result screen. +## Run: godot --path . --resolution 1920x1080 res://tools/menu_review.tscn +var main: Node3D +var captures := "res://docs/screenshots/phase20/after" +var tag := "" +func _ready() -> void: + call_deferred("run") +func shot(name: String, frames: int = 14) -> void: + for n: int in range(frames): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + "-" + tag + ".png") + print("MENU_SHOT: ", name, " ", get_viewport().get_texture().get_size()) +func wait_stage() -> void: + var stage: Node3D = main.hud.main_menu.stage + while not (stage.is_ready("glutpakt") and stage.is_ready("wurzelbund")): + await get_tree().process_frame + while stage.is_moving(): + await get_tree().process_frame +func run() -> void: + tag = "%dx%d" % [get_window().size.x, get_window().size.y] + Soundscape.enabled = false + WaveManager.set_physics_process(false) + GameState.factions = ["wurzelbund", "glutpakt"] + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + var menu: MainMenu = main.hud.main_menu + await wait_stage() + await shot("title") + menu.new_game_button.pressed.emit() + await wait_stage() + await shot("setup-wurzelbund", 30) + menu.faction_choice.cards[0].pressed.emit() + await wait_stage() + await shot("setup-glutpakt", 30) + menu._toggle_advanced() + await shot("setup-advanced") + menu._toggle_advanced() + # Real keyboard navigation: focus starts on the selected card, Right moves to the other one. + menu.faction_choice.focus_selected() + await get_tree().process_frame + for code: Key in [KEY_RIGHT]: + var press := InputEventKey.new() + press.keycode = code + press.physical_keycode = code + press.pressed = true + get_viewport().push_input(press) + var release := press.duplicate() + release.pressed = false + get_viewport().push_input(release) + print("FOCUS_OWNER: ", get_viewport().gui_get_focus_owner().name if get_viewport().gui_get_focus_owner() != null else "none") + await shot("setup-focus") + main.hud.toggle_settings() + await shot("options") + main.hud.toggle_settings() + GameState.set_phase(GameState.Phase.GAME_OVER) + GameState.outcome = 0 + GameState.wave = 20 + main.hud._phase_changed(GameState.phase) + await wait_stage() + await shot("result") + # The HUD after the menu hands over: same panels, now on a 16:9 canvas. + GameState.reset_match() + await wait_stage() + menu.new_game_button.pressed.emit() + menu.start_button.pressed.emit() + await get_tree().create_timer(.5).timeout + main.hud._starter_button.pressed.emit() + await shot("ingame-build", 20) + print("MENU_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/menu_review.gd.uid b/tools/menu_review.gd.uid new file mode 100644 index 0000000..3d907aa --- /dev/null +++ b/tools/menu_review.gd.uid @@ -0,0 +1 @@ +uid://jiopw3ff6irm diff --git a/tools/menu_review.tscn b/tools/menu_review.tscn new file mode 100644 index 0000000..736cbe1 --- /dev/null +++ b/tools/menu_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/menu_review.gd" id="1"] + +[node name="MenuReview" type="Node"] +script = ExtResource("1") diff --git a/tools/model_contact_sheet.gd b/tools/model_contact_sheet.gd new file mode 100644 index 0000000..31e769d --- /dev/null +++ b/tools/model_contact_sheet.gd @@ -0,0 +1,130 @@ +extends Node +## Real Godot renders. Use model_gallery.tscn -- --capture after GLB import. + +const STAGE: Script = preload("res://tools/model_gallery_stage.gd") +const OUT_DIR: String = "res://docs/screenshots/phase4" +const GROUPS: Array[Dictionary] = [ + {"key": "glutpakt", "title": "GLUTPAKT", "subtitle": "Basalt · Orangeglut · Messing"}, + {"key": "nietenkonvent", "title": "NIETENKONVENT", "subtitle": "Petrol · Ocker · Stahl · Keramik"}, + {"key": "nebelchor", "title": "NEBELCHOR", "subtitle": "Indigo · Violett · Mint · Nebel"}, + {"key": "wurzelbund", "title": "WURZELBUND", "subtitle": "Borke · Moos · Blatt · Blüte"}, + {"key": "neutral", "title": "SÖLDNER & ARBEITER", "subtitle": "Fünf Send-Einheiten und der Funkenleser"}, + {"key": "rift", "title": "RISSKREATUREN", "subtitle": "Schalen · Knochen · Rissglut"}, + {"key": "environment", "title": "SPIELFELD & SAUMKERNE", "subtitle": "Modulares Lane-Segment und zwei Teamkerne"} +] + +var _assets: Array[Dictionary] = [] +var _sheet: Control +var _views: Array[Dictionary] = [] + + +func _ready() -> void: + var manifest: String = "res://assets/phase4_manifest.json" + if not FileAccess.file_exists(manifest): + _fail("Phase 4 manifest is missing; export all models first.") + return + var data: Variant = JSON.parse_string(FileAccess.get_file_as_string(manifest)) + if not data is Dictionary: + _fail("Invalid Phase 4 manifest.") + return + for value: Variant in data.get("assets", []): + if value is Dictionary: + _assets.append(value) + if _assets.size() != 59: + _fail("Expected 59 exported models, found %d." % _assets.size()) + return + for asset: Dictionary in _assets: + if not ResourceLoader.exists(str(asset.get("resource_path", ""))): + _fail("Model has not been imported: " + str(asset.get("id", "?"))) + return + DirAccess.make_dir_recursive_absolute(OUT_DIR) + get_window().size = Vector2i(1600, 960) + get_tree().create_timer(90.0).timeout.connect(func() -> void: _fail("Capture timed out.")) + for group: Dictionary in GROUPS: + if not _build_sheet(group): + return + await get_tree().process_frame + await get_tree().process_frame + await RenderingServer.frame_post_draw + await get_tree().create_timer(0.25).timeout + var image: Image = get_viewport().get_texture().get_image() + var output: String = OUT_DIR + "/models-" + str(group["key"]) + ".png" + var error: Error = image.save_png(output) + if error != OK: + _fail("Could not save " + output) + return + print("CAPTURED ", output, " (", image.get_width(), "×", image.get_height(), ")") + _sheet.free() + _views.clear() + print("PASS: captured all 59 models in seven real Godot contact sheets.") + get_tree().quit(0) + + +func _build_sheet(group: Dictionary) -> bool: + var selected: Array[Dictionary] = [] + var key: String = str(group["key"]) + for asset: Dictionary in _assets: + var matches: bool = str(asset.get("faction", "")) == key + if key == "environment": + matches = str(asset.get("role", "")) in ["core", "lane"] + if matches: + selected.append(asset) + _sheet = Control.new() + _sheet.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(_sheet) + var background: ColorRect = ColorRect.new() + background.color = Color("10141b") + background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _sheet.add_child(background) + var margin: MarginContainer = MarginContainer.new() + margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + for edge: String in ["left", "right"]: + margin.add_theme_constant_override("margin_" + edge, 28) + for edge: String in ["top", "bottom"]: + margin.add_theme_constant_override("margin_" + edge, 22) + _sheet.add_child(margin) + var layout: VBoxContainer = VBoxContainer.new() + layout.add_theme_constant_override("separation", 12) + margin.add_child(layout) + layout.add_child(_label("SAUMWACHT / " + str(group["title"]), 30, Color("ddc898"))) + layout.add_child(_label("Phase 4 · " + str(group["subtitle"]) + " · %d Modelle" % selected.size(), 17, Color("abb5c5"))) + var grid: GridContainer = GridContainer.new() + grid.columns = 3 if selected.size() <= 6 else 5 + grid.size_flags_vertical = Control.SIZE_EXPAND_FILL + grid.size_flags_horizontal = Control.SIZE_EXPAND_FILL + grid.add_theme_constant_override("h_separation", 12) + grid.add_theme_constant_override("v_separation", 16) + layout.add_child(grid) + for asset: Dictionary in selected: + var card: VBoxContainer = VBoxContainer.new() + card.size_flags_horizontal = Control.SIZE_EXPAND_FILL + card.size_flags_vertical = Control.SIZE_EXPAND_FILL + card.add_theme_constant_override("separation", 5) + grid.add_child(card) + var view: Dictionary = STAGE.create(card, Vector2(270, 230)) + _views.append(view) + if not STAGE.show_asset(view, asset): + _fail("Capture failed to load " + str(asset["id"])) + return false + STAGE.add_id_tag(view, str(asset["id"])) + var title: Label = _label(str(asset["name"]), 19, Color("eee6d8")) + title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + card.add_child(title) + var detail: Label = _label("%s · %d Dreiecke" % [str(asset["id"]).to_upper(), int(asset.get("triangles", 0))], 14, Color("a1acbd")) + detail.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + card.add_child(detail) + layout.add_child(_label("Originale parametrisierte Modelle · Einheitliche Studiobeleuchtung · Vorschau proportional auf gemeinsame Bühne eingepasst", 14, Color("8491a3"))) + return true + + +func _label(text: String, font_size: int, color: Color) -> Label: + var result: Label = Label.new() + result.text = text + result.add_theme_font_size_override("font_size", font_size) + result.add_theme_color_override("font_color", color) + return result + + +func _fail(message: String) -> void: + printerr("FAIL: ", message) + get_tree().quit(1) diff --git a/tools/model_contact_sheet.gd.uid b/tools/model_contact_sheet.gd.uid new file mode 100644 index 0000000..600d028 --- /dev/null +++ b/tools/model_contact_sheet.gd.uid @@ -0,0 +1 @@ +uid://dhseg0gow4sgi diff --git a/tools/model_gallery.gd b/tools/model_gallery.gd new file mode 100644 index 0000000..3232497 --- /dev/null +++ b/tools/model_gallery.gd @@ -0,0 +1,215 @@ +extends Control +## Standalone Phase 4 review. F6, or run this scene with -- --capture. + +const STAGE: Script = preload("res://tools/model_gallery_stage.gd") +const MANIFEST: String = "res://assets/phase4_manifest.json" +const FACTIONS: Dictionary = { + "all": "Alle Modelle", "glutpakt": "Glutpakt", "nietenkonvent": "Nietenkonvent", + "nebelchor": "Nebelchor", "wurzelbund": "Wurzelbund", "neutral": "Söldner & Arbeiter", + "environment": "Spielfeld & Saumkerne", "rift": "Risskreaturen" +} +const ROLES: Dictionary = { + "melee": "Nahkampf", "tank": "Tank", "ranged": "Fernkampf", + "artillery": "Artillerie", "support": "Unterstützung", "mercenary": "Söldner", + "enemy": "Wellengegner", "worker": "Arbeiter", "lane": "Lane-Segment", "core": "Saumkern" +} + +var _assets: Array[Dictionary] = [] +var _filtered: Array[Dictionary] = [] +var _icon_paths: Dictionary = {} +var _faction_select: OptionButton +var _asset_select: OptionButton +var _title: Label +var _details: Label +var _icon: TextureRect +var _reference_note: Label +var _auto_rotate: CheckButton +var _view: Dictionary = {} + + +func _ready() -> void: + set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + if "--compare" in OS.get_cmdline_user_args(): + var comparison_script: Script = load("res://tools/model_reference_sheet.gd") as Script + add_child(comparison_script.new()) + return + if "--capture" in OS.get_cmdline_user_args(): + var capture_script: Script = load("res://tools/model_contact_sheet.gd") as Script + var capture: Node = capture_script.new() as Node + add_child(capture) + return + _load_catalog() + _build_interface() + _filter_assets(0) + + +func _load_catalog() -> void: + if not FileAccess.file_exists(MANIFEST): + push_error("Phase 4 manifest missing. Export and import models first.") + return + var data: Variant = JSON.parse_string(FileAccess.get_file_as_string(MANIFEST)) + if data is Dictionary: + for value: Variant in data.get("assets", []): + if value is Dictionary: + _assets.append(value) + var icon_manifest: String = "res://assets/phase3_manifest.json" + if FileAccess.file_exists(icon_manifest): + var icons: Variant = JSON.parse_string(FileAccess.get_file_as_string(icon_manifest)) + if icons is Dictionary: + for value: Variant in icons.get("assets", []): + if value is Dictionary: + _icon_paths[str(value.get("id", ""))] = str(value.get("resource_path", "")) + + +func _build_interface() -> void: + var backdrop: ColorRect = ColorRect.new() + backdrop.color = Color("11151b") + backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + backdrop.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(backdrop) + var margin: MarginContainer = MarginContainer.new() + margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + for edge: String in ["left", "top", "right", "bottom"]: + margin.add_theme_constant_override("margin_" + edge, 24) + add_child(margin) + var layout: VBoxContainer = VBoxContainer.new() + layout.add_theme_constant_override("separation", 18) + margin.add_child(layout) + var heading: Label = _label("SAUMWACHT / 3D-WERKSTATT", 27, Color("ddc898")) + layout.add_child(heading) + layout.add_child(_label("%d Modelle · Glutpakt und Risskreaturen in hoher Detailstufe" % _assets.size(), 17, Color("a8b0bd"))) + var body: HBoxContainer = HBoxContainer.new() + body.size_flags_vertical = Control.SIZE_EXPAND_FILL + body.add_theme_constant_override("separation", 24) + layout.add_child(body) + var sidebar: VBoxContainer = VBoxContainer.new() + sidebar.custom_minimum_size.x = 320 + sidebar.add_theme_constant_override("separation", 14) + body.add_child(sidebar) + sidebar.add_child(_label("FRAKTION", 13, Color("c4b58f"))) + _faction_select = OptionButton.new() + _faction_select.custom_minimum_size.y = 42 + _faction_select.add_theme_font_size_override("font_size", 18) + for key: String in FACTIONS: + _faction_select.add_item(FACTIONS[key]) + _faction_select.set_item_metadata(_faction_select.item_count - 1, key) + _faction_select.item_selected.connect(_filter_assets) + sidebar.add_child(_faction_select) + sidebar.add_child(_label("MODELL", 13, Color("c4b58f"))) + _asset_select = OptionButton.new() + _asset_select.custom_minimum_size.y = 42 + _asset_select.add_theme_font_size_override("font_size", 17) + _asset_select.fit_to_longest_item = false + _asset_select.item_selected.connect(_select_asset) + sidebar.add_child(_asset_select) + _title = _label("", 24, Color("f1e8d6")) + _title.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + sidebar.add_child(_title) + _details = _label("", 16, Color("b8bfca")) + _details.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + sidebar.add_child(_details) + _icon = TextureRect.new() + _icon.custom_minimum_size = Vector2(256, 200) + _icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + _icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + _icon.size_flags_vertical = Control.SIZE_EXPAND_FILL + sidebar.add_child(_icon) + _reference_note = _label("Iconreferenz · Phase 3", 14, Color("8e99aa")) + sidebar.add_child(_reference_note) + _auto_rotate = CheckButton.new() + _auto_rotate.text = "Automatisch drehen" + _auto_rotate.add_theme_font_size_override("font_size", 16) + sidebar.add_child(_auto_rotate) + var reset: Button = Button.new() + reset.text = "Ansicht zurücksetzen" + reset.custom_minimum_size.y = 38 + reset.pressed.connect(_reset_view) + sidebar.add_child(reset) + var preview_box: PanelContainer = PanelContainer.new() + preview_box.size_flags_horizontal = Control.SIZE_EXPAND_FILL + preview_box.size_flags_vertical = Control.SIZE_EXPAND_FILL + body.add_child(preview_box) + _view = STAGE.create(preview_box, Vector2(520, 480)) + var container: SubViewportContainer = _view["container"] as SubViewportContainer + container.gui_input.connect(_on_preview_input) + layout.add_child(_label("Ziehen: Modell drehen · Mausrad: Zoom · Originalmodelle bleiben unverändert", 15, Color("939dab"))) + + +func _label(text: String, font_size: int, color: Color) -> Label: + var result: Label = Label.new() + result.text = text + result.add_theme_font_size_override("font_size", font_size) + result.add_theme_color_override("font_color", color) + return result + + +func _filter_assets(index: int) -> void: + _filtered.clear() + _asset_select.clear() + var faction: String = str(_faction_select.get_item_metadata(index)) + for asset: Dictionary in _assets: + var matches: bool = faction == "all" or str(asset.get("faction", "")) == faction + if faction == "environment": + matches = str(asset.get("role", "")) in ["lane", "core"] + if matches: + _filtered.append(asset) + _asset_select.add_item(str(asset["id"]).to_upper() + " · " + str(asset["name"])) + if not _filtered.is_empty(): + _asset_select.select(0) + _select_asset(0) + else: + _title.text = "Keine Modelle vorhanden" + _details.text = "Blender-Export und Godot-Import zuerst ausführen." + _icon.texture = null + + +func _select_asset(index: int) -> void: + if index < 0 or index >= _filtered.size(): + return + var asset: Dictionary = _filtered[index] + _title.text = str(asset["name"]) + var role: String = str(asset.get("role", "")) + var bounds: Dictionary = asset.get("bounds_godot", {}) + var low: Array = bounds.get("min", [0, 0, 0]) + var high: Array = bounds.get("max", [0, 0, 0]) + var dimensions: Vector3 = Vector3(float(high[0])-float(low[0]), float(high[1])-float(low[1]), float(high[2])-float(low[2])) + _details.text = "%s · %s\n%d Dreiecke\nB %.2f m · H %.2f m · T %.2f m" % [ + str(asset["id"]).to_upper(), str(ROLES.get(role, role)), int(asset.get("triangles", 0)), + dimensions.x, dimensions.y, dimensions.z] + var icon_id: String = str(asset["id"]) + if icon_id == "worker": + icon_id = "worker_funkenleser" + var icon_path: String = str(_icon_paths.get(icon_id, "")) + _icon.texture = load(icon_path) as Texture2D if not icon_path.is_empty() else null + _reference_note.visible = _icon.texture != null + if not STAGE.show_asset(_view, asset): + _details.text += "\nModell konnte nicht geladen werden." + _reset_view() + + +func _process(delta: float) -> void: + if _auto_rotate != null and _auto_rotate.button_pressed and not _view.is_empty(): + var turntable: Node3D = _view["turntable"] as Node3D + turntable.rotate_y(delta * 0.38) + + +func _reset_view() -> void: + if _view.is_empty(): + return + var turntable: Node3D = _view["turntable"] as Node3D + var camera: Camera3D = _view["camera"] as Camera3D + turntable.rotation = Vector3.ZERO + camera.size = 2.9 + + +func _on_preview_input(event: InputEvent) -> void: + var camera: Camera3D = _view["camera"] as Camera3D + var turntable: Node3D = _view["turntable"] as Node3D + if event is InputEventMouseButton and event.pressed: + if event.button_index == MOUSE_BUTTON_WHEEL_UP: + camera.size = clampf(camera.size * 0.90, 1.6, 5.5) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + camera.size = clampf(camera.size * 1.10, 1.6, 5.5) + if event is InputEventMouseMotion and Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + _auto_rotate.button_pressed = false + turntable.rotate_y(event.relative.x * 0.008) diff --git a/tools/model_gallery.gd.uid b/tools/model_gallery.gd.uid new file mode 100644 index 0000000..8fd579a --- /dev/null +++ b/tools/model_gallery.gd.uid @@ -0,0 +1 @@ +uid://ws5k2jac7rhw diff --git a/tools/model_gallery.tscn b/tools/model_gallery.tscn new file mode 100644 index 0000000..e61934e --- /dev/null +++ b/tools/model_gallery.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/model_gallery.gd" id="1_gallery"] + +[node name="ModelGallery" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_gallery") diff --git a/tools/model_gallery_stage.gd b/tools/model_gallery_stage.gd new file mode 100644 index 0000000..aa71def --- /dev/null +++ b/tools/model_gallery_stage.gd @@ -0,0 +1,112 @@ +extends RefCounted +## Shared, isolated studio. All geometry belongs to this preview only. + + +static func create(parent: Control, minimum: Vector2 = Vector2(280, 260)) -> Dictionary: + var container: SubViewportContainer = SubViewportContainer.new() + container.custom_minimum_size = minimum + container.size_flags_horizontal = Control.SIZE_EXPAND_FILL + container.size_flags_vertical = Control.SIZE_EXPAND_FILL + container.stretch = true + parent.add_child(container) + var viewport: SubViewport = SubViewport.new() + viewport.size = Vector2i(minimum) + viewport.own_world_3d = true + viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS + viewport.msaa_3d = Viewport.MSAA_4X + container.add_child(viewport) + var studio: Node3D = Node3D.new() + studio.name = "PreviewStudio" + viewport.add_child(studio) + var environment_node: WorldEnvironment = WorldEnvironment.new() + var environment: Environment = Environment.new() + preload("res://scripts/presentation/lighting.gd").configure(environment, true) + environment_node.environment = environment + studio.add_child(environment_node) + var key: DirectionalLight3D = DirectionalLight3D.new() + key.rotation_degrees = Vector3(-42, -33, 0) + key.light_color = Color("fff0df") + key.light_energy = 1.9 + key.shadow_enabled = true + studio.add_child(key) + var fill: DirectionalLight3D = DirectionalLight3D.new() + fill.rotation_degrees = Vector3(-30, 145, 0) + fill.light_color = Color("cfdef0") + fill.light_energy = .6 + studio.add_child(fill) + var floor_mesh: CylinderMesh = CylinderMesh.new() + floor_mesh.top_radius = 1.16 + floor_mesh.bottom_radius = 1.20 + floor_mesh.height = 0.075 + floor_mesh.radial_segments = 48 + var floor_material: StandardMaterial3D = StandardMaterial3D.new() + floor_material.albedo_color = Color("34383e") + floor_material.roughness = 0.92 + floor_mesh.material = floor_material + var floor: MeshInstance3D = MeshInstance3D.new() + floor.name = "PreviewPedestal" + floor.mesh = floor_mesh + floor.position.y = -0.043 + studio.add_child(floor) + var turntable: Node3D = Node3D.new() + turntable.name = "Turntable" + studio.add_child(turntable) + var camera: Camera3D = Camera3D.new() + camera.projection = Camera3D.PROJECTION_ORTHOGONAL + camera.size = 2.9 + camera.position = Vector3(3.4, 2.7, 4.6) + studio.add_child(camera) + camera.look_at(Vector3(0, 0.67, 0), Vector3.UP) + camera.current = true + return {"container": container, "viewport": viewport, "studio": studio, + "turntable": turntable, "camera": camera} + + +static func show_asset(view: Dictionary, asset: Dictionary) -> bool: + var turntable: Node3D = view["turntable"] as Node3D + for child: Node in turntable.get_children(): + child.free() + turntable.rotation = Vector3.ZERO + var path: String = str(asset.get("resource_path", "")) + var packed: PackedScene = load(path) as PackedScene + if packed == null: + push_error("Model gallery cannot load " + path) + return false + var model: Node3D = packed.instantiate() as Node3D + if model == null: + push_error("Model gallery expected a Node3D: " + path) + return false + turntable.add_child(model) + AssetLibrary.decorate_model(model) + var bounds: Dictionary = asset.get("bounds_godot", {}) + var minimum: Array = bounds.get("min", [-0.5, 0.0, -0.5]) + var maximum: Array = bounds.get("max", [0.5, 1.5, 0.5]) + var low: Vector3 = Vector3(float(minimum[0]), float(minimum[1]), float(minimum[2])) + var high: Vector3 = Vector3(float(maximum[0]), float(maximum[1]), float(maximum[2])) + var dimensions: Vector3 = high - low + var extent: float = maxf(maxf(dimensions.x, dimensions.z), dimensions.y * 1.05) + var factor: float = 1.74 / maxf(extent, 0.001) + var center: Vector3 = (low + high) * 0.5 + model.scale = Vector3.ONE * factor + model.position = -Vector3(center.x, low.y, center.z) * factor + var camera: Camera3D = view["camera"] as Camera3D + camera.size = 3.8 if str(asset.get("role", "")) in ["core", "lane"] else 2.9 + return true + + +static func add_id_tag(view: Dictionary, asset_id: String) -> void: + var studio: Node3D = view["studio"] as Node3D + var label: Label3D = Label3D.new() + label.text = asset_id.to_upper() + if asset_id == "map_lane_segment": + label.text = "LANE" + elif asset_id.begins_with("core_team"): + label.text = "KERN " + asset_id.right(1) + label.font_size = 36 + label.pixel_size = 0.0025 + label.modulate = Color("c9b88f") + label.outline_size = 0 + label.no_depth_test = true + label.billboard = BaseMaterial3D.BILLBOARD_ENABLED + label.position = Vector3(0, -0.10, 0.94) + studio.add_child(label) diff --git a/tools/model_gallery_stage.gd.uid b/tools/model_gallery_stage.gd.uid new file mode 100644 index 0000000..214c1ed --- /dev/null +++ b/tools/model_gallery_stage.gd.uid @@ -0,0 +1 @@ +uid://6rfntc3kb410 diff --git a/tools/model_reference_sheet.gd b/tools/model_reference_sheet.gd new file mode 100644 index 0000000..c99e133 --- /dev/null +++ b/tools/model_reference_sheet.gd @@ -0,0 +1,89 @@ +extends Node +## Direct icon/model comparisons; original PNGs stay unchanged. + +const STAGE: Script = preload("res://tools/model_gallery_stage.gd") +var _sheet: Control + +func _ready() -> void: + get_tree().create_timer(90).timeout.connect(func(): get_tree().quit(1)) + var faction: String = "glutpakt" + for arg: String in OS.get_cmdline_user_args(): + if arg.begins_with("--faction="): + faction = arg.trim_prefix("--faction=") + var data: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://assets/phase4_manifest.json")) + var icons: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://assets/phase3_manifest.json")) + var paths: Dictionary = {} + for asset: Dictionary in icons["assets"]: + paths[str(asset["id"])] = str(asset["resource_path"]) + paths["worker"] = paths.get("worker_funkenleser", "") + var selected: Array[Dictionary] = [] + for asset: Dictionary in data["assets"]: + if str(asset["faction"]) == faction and paths.has(str(asset["id"])): + selected.append(asset) + get_window().size = Vector2i(1600, 960) + for start: int in range(0, selected.size(), 2): + _sheet = Control.new() + _sheet.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + add_child(_sheet) + var backdrop: ColorRect = ColorRect.new() + backdrop.color = Color("10141b") + backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + _sheet.add_child(backdrop) + var margin: MarginContainer = MarginContainer.new() + margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + for edge: String in ["left", "top", "right", "bottom"]: + margin.add_theme_constant_override("margin_" + edge, 24) + _sheet.add_child(margin) + var layout: VBoxContainer = VBoxContainer.new() + layout.add_theme_constant_override("separation", 16) + margin.add_child(layout) + layout.add_child(_label("SAUMWACHT / " + faction.to_upper(), 29, Color("ddc898"))) + layout.add_child(_label("Bildreferenz und überarbeitetes 3D-Modell · Gleiche Einheit, direkte Gegenüberstellung", 18, Color("adb6c5"))) + var row: HBoxContainer = HBoxContainer.new() + row.size_flags_vertical = Control.SIZE_EXPAND_FILL + row.add_theme_constant_override("separation", 12) + layout.add_child(row) + for index: int in range(start, mini(start + 2, selected.size())): + var asset: Dictionary = selected[index] + for reference: bool in [true, false]: + var card: VBoxContainer = VBoxContainer.new() + card.size_flags_horizontal = Control.SIZE_EXPAND_FILL + row.add_child(card) + card.add_child(_label("ICON · PHASE 3" if reference else "3D-MODELL", 16, Color("aab3c2"))) + if reference: + var icon: TextureRect = TextureRect.new() + # Compare against native PNG pixels, not the 256px gameplay import. + var source_image: Image = Image.load_from_file(str(paths[str(asset["id"])])) + icon.texture = ImageTexture.create_from_image(source_image) + icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + icon.custom_minimum_size.x = 350 + icon.size_flags_vertical = Control.SIZE_EXPAND_FILL + card.add_child(icon) + else: + var view: Dictionary = STAGE.create(card, Vector2(350, 450)) + STAGE.show_asset(view, asset) + (view["camera"] as Camera3D).size = 3.5 + card.add_child(_label(str(asset["id"]).to_upper() + " · " + str(asset["name"]), 19, Color("eee6d8"))) + card.add_child(_label("Originalillustration" if reference else str(int(asset["triangles"])) + " Dreiecke · GLB", 15, Color("9ca9bc"))) + layout.add_child(_label("3D-Darstellung aus Godot · Modellierte Formdetails und PBR-Materialien · Bearbeitbare Blender-Quellen", 14, Color("8491a3"))) + await get_tree().process_frame + await get_tree().process_frame + await RenderingServer.frame_post_draw + await get_tree().create_timer(0.2).timeout + var output: String = "res://docs/screenshots/phase4/reference-" + str(selected[start]["id"]) + ".png" + var error: Error = get_viewport().get_texture().get_image().save_png(output) + if error != OK: + printerr("Reference screenshot failed: ", output) + get_tree().quit(1) + return + print("REFERENCE_CAPTURED ", output) + _sheet.free() + get_tree().quit(0) + +func _label(text: String, size: int, color: Color) -> Label: + var label: Label = Label.new() + label.text = text + label.add_theme_font_size_override("font_size", size) + label.add_theme_color_override("font_color", color) + return label diff --git a/tools/model_reference_sheet.gd.uid b/tools/model_reference_sheet.gd.uid new file mode 100644 index 0000000..036c743 --- /dev/null +++ b/tools/model_reference_sheet.gd.uid @@ -0,0 +1 @@ +uid://jxpdhqxvwto1 diff --git a/tools/model_reference_sheet.tscn b/tools/model_reference_sheet.tscn new file mode 100644 index 0000000..5f67e25 --- /dev/null +++ b/tools/model_reference_sheet.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/model_reference_sheet.gd" id="1"] + +[node name="ReferenceSheet" type="Node"] +script = ExtResource("1") diff --git a/tools/phase10_art_review.gd b/tools/phase10_art_review.gd new file mode 100644 index 0000000..549a906 --- /dev/null +++ b/tools/phase10_art_review.gd @@ -0,0 +1,46 @@ +extends Node +## Captures the actual runtime scene and actual in-game model inspector. +var main: Node3D +var directory := "res://docs/screenshots/phase10" + +func _ready() -> void: + call_deferred("run") + +func capture(label: String) -> void: + for frame: int in range(12): + await get_tree().process_frame + await RenderingServer.frame_post_draw + var result: Error = get_viewport().get_texture().get_image().save_png(directory + "/" + label + ".png") + assert(result == OK) + print("ART_CAPTURE: ", label) + +func run() -> void: + DirAccess.make_dir_recursive_absolute(directory) + get_window().size = Vector2i(1920,1080) + GameState.factions = ["wurzelbund","glutpakt"] + GameState.timed_build = false + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + await capture("menu") + main._start_match() + main._starter() + await capture("build") + main._show_base() + await capture("base") + main._show_base() + # Studio uses only the same GLBs and shaders that the match uses. + for id: String in ["w04","w08","w10","g02","g04"]: + main.hud.model_inspector.show_model(id) + main.hud.model_inspector._rotate = false + main.hud.model_inspector._turntable.rotation.y = -.2 + await capture("model-" + id) + main.hud.model_inspector.hide_model() + main.hud.hide() + main._manual_camera = true + main.camera.size = 49 + main.camera.position = Vector3(35,56,52) + main.camera.look_at(Vector3(0,0,1)) + await capture("map-overview") + await Soundscape.quit_game() diff --git a/tools/phase10_art_review.gd.uid b/tools/phase10_art_review.gd.uid new file mode 100644 index 0000000..0db5360 --- /dev/null +++ b/tools/phase10_art_review.gd.uid @@ -0,0 +1 @@ +uid://bpw5gbooef5gd diff --git a/tools/phase10_art_review.tscn b/tools/phase10_art_review.tscn new file mode 100644 index 0000000..d743ede --- /dev/null +++ b/tools/phase10_art_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/phase10_art_review.gd" id="1"] + +[node name="Phase10ArtReview" type="Node"] +script = ExtResource("1") diff --git a/tools/prepare_phase3_assets.py b/tools/prepare_phase3_assets.py new file mode 100644 index 0000000..232884d --- /dev/null +++ b/tools/prepare_phase3_assets.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +"""Validate and copy native Phase 3 PNGs; never resample or edit image pixels. + +Requires Pillow for read-only PNG inspection. Run once, let Godot import, then run +with --import-settings and import again to apply the 256px icon texture limit. +""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path +import re +import shutil + +from PIL import Image + +PROJECT = Path(__file__).resolve().parents[1] +SOURCE = PROJECT / "assets-source" / "phase3" + + +def digest(path: Path) -> str: + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def write_json(path: Path, value: object) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + + +def source_master(record: dict) -> Path: + given = Path(record["master_path"]) + # Preserve portability when the project is copied to another machine. + index = given.parts.index("masters") + candidate = SOURCE.joinpath(*given.parts[index:]).resolve() + if not candidate.is_relative_to(SOURCE / "masters"): + raise ValueError("Master path escapes the asset directory") + return candidate + + +def inspect_assets() -> list[dict]: + planned = json.loads((SOURCE / "asset_plan.json").read_text(encoding="utf-8"))["assets"] + if len(planned) != 66 or len({entry["id"] for entry in planned}) != 66: + raise ValueError("Expected 66 unique planned assets") + result = [] + for entry in planned: + record_file = SOURCE / "records" / (entry["id"] + ".json") + record = json.loads(record_file.read_text(encoding="utf-8")) + for field in ("id", "display_name", "faction", "kind"): + if record[field] != entry[field]: + raise ValueError(f"{entry['id']}: {field} differs from plan") + if not record.get("prompt") or not record.get("description_de"): + raise ValueError(f"{entry['id']}: missing prompt or description") + master = source_master(record) + checksum = digest(master) + original = Path(record["source_path"]) + if original.is_file() and digest(original) != checksum: + raise ValueError(f"{entry['id']}: master differs from generated original") + with Image.open(master) as image: + image.load() + width, height = image.size + if image.format != "PNG": + raise ValueError(f"{entry['id']}: not PNG") + alpha_range = None + if entry["requires_alpha"]: + if image.mode != "RGBA": + raise ValueError(f"{entry['id']}: expected actual RGBA transparency") + alpha = image.getchannel("A") + alpha_range = list(alpha.getextrema()) + if alpha_range[0] != 0 or alpha_range[1] < 200: + raise ValueError(f"{entry['id']}: missing transparent or visible pixels") + if alpha.getpixel((0, 0)) > 2: + raise ValueError(f"{entry['id']}: outer corner is not transparent") + if entry["kind"] == "ui_frame" and alpha.getpixel((width // 2, height // 2)) > 2: + raise ValueError(f"{entry['id']}: frame center must be transparent") + if entry["kind"].endswith("_icon") and width != height: + raise ValueError(f"{entry['id']}: icon is not square") + mode = image.mode + folder = "icons/" + entry["faction"] if entry["kind"].endswith("_icon") else ("ui" if entry["faction"] == "ui" else "concepts") + target = PROJECT / "assets" / folder / master.name + result.append({**entry, "description_de": record["description_de"], + "resource_path": "res://" + target.relative_to(PROJECT).as_posix(), + "master_path": master.relative_to(PROJECT).as_posix(), + "record_path": record_file.relative_to(PROJECT).as_posix(), + "width": width, "height": height, "mode": mode, + "alpha_range": alpha_range, "sha256": checksum, + "generation_mode": record.get("generation_mode", "built-in"), + "status": "prepared"}) + return result + + +def apply_import_settings(assets: list[dict]) -> None: + configs = [] + for asset in assets: + path = PROJECT / (asset["resource_path"].removeprefix("res://") + ".import") + if not path.is_file(): + raise ValueError(f"Import config missing: {path}; run Godot --editor --import --quit first") + content = path.read_text(encoding="utf-8") + settings = {"process/size_limit": str(asset["import_size_limit"]), + "compress/mode": "0", "mipmaps/generate": "false", + "process/fix_alpha_border": "true", "process/premult_alpha": "false"} + for key, value in settings.items(): + content, count = re.subn(r"(?m)^" + re.escape(key) + r"=.*$", key + "=" + value, content) + if count != 1: + raise ValueError(f"{path.name}: missing or repeated setting {key}") + configs.append((path, content)) + for path, content in configs: + if path.read_text(encoding="utf-8") != content: + path.write_text(content, encoding="utf-8") + + +def prepare(assets: list[dict]) -> None: + for asset in assets: + target = PROJECT / asset["resource_path"].removeprefix("res://") + master = PROJECT / asset["master_path"] + target.parent.mkdir(parents=True, exist_ok=True) + if not target.is_file() or digest(target) != asset["sha256"]: + shutil.copyfile(master, target) + if digest(target) != asset["sha256"]: + raise ValueError(f"Copy checksum mismatch: {asset['id']}") + manifest = {"phase": 3, "asset_count": len(assets), + "note": "Native PNG masters; 56 icon textures use a Godot import limit of 256px. Gameplay integration follows in Phase 5.", + "assets": assets} + write_json(PROJECT / "assets" / "phase3_manifest.json", manifest) + write_json(PROJECT / "assets" / "icons" / "manifest.json", + {"phase": 3, "assets": [a for a in assets if a["kind"].endswith("_icon")]}) + records = [json.loads((PROJECT / a["record_path"]).read_text(encoding="utf-8")) for a in assets] + write_json(SOURCE / "all-prompts.json", {"phase": 3, "assets": records}) + lines = ["# Phase 3 · Assetkatalog", "", "66 einzeln generierte Assets für Saumwacht. Alle PNG-Masters bleiben in nativer Auflösung erhalten; die 56 Icons werden in Godot als 256 × 256 Texturen importiert.", "", "[Interaktive Galerie](gallery.html) · [Prompts und Herkunft](all-prompts.json)", "", "| ID | Name | Gruppe | PNG | Beschreibung |", "| --- | --- | --- | --- | --- |"] + for asset in assets: + path = Path(asset["master_path"]).relative_to("assets-source/phase3").as_posix() + lines.append(f"| `{asset['id']}` | [{asset['display_name']}]({path}) | {asset['faction']} | {asset['width']} × {asset['height']} | {asset['description_de'].replace('|', '/')} |") + (SOURCE / "catalog.md").write_text("\n".join(lines) + "\n", encoding="utf-8") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--import-settings", action="store_true", help="Apply limits to existing Godot .import files") + args = parser.parse_args() + assets = inspect_assets() # Validate the complete batch before copying any files. + prepare(assets) + if args.import_settings: + apply_import_settings(assets) + print(f"PASS: {len(assets)} native PNGs validated and copied without pixel changes; manifests and catalog written.") + if not args.import_settings: + print("Next: Godot import, rerun with --import-settings, then Godot reimport and verify_phase3_imports.gd.") + + +if __name__ == "__main__": + main() diff --git a/tools/quell_review.gd b/tools/quell_review.gd new file mode 100644 index 0000000..dd2746b --- /dev/null +++ b/tools/quell_review.gd @@ -0,0 +1,33 @@ +extends Node +var main: Node3D +var captures := "res://docs/screenshots/phase16" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") +func run() -> void: + get_window().size = Vector2i(1600, 1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("w10") + print("QUELL_MODEL: ", main.hud.model_inspector.model_id, " caption=", main.hud.model_inspector._caption.text, " path=", AssetLibrary._models.get("w10", {}).get("resource_path"), " tris=", AssetLibrary._models.get("w10", {}).get("triangles")) + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + studio._turntable.rotation.y = -.15 + await shot("quell-front") + studio._turntable.rotation.y = PI + await shot("quell-back") + studio._turntable.rotation.y = -.15 + for clip: String in ["walk", "attack_a", "ability", "death"]: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip: + studio._clip_selector.select(i) + studio._clip_time = .55 if clip == "walk" else (.9 if clip == "attack_a" else (1.0 if clip == "ability" else 1.2)) + await shot("pose-" + clip) + print("QUELL_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/quell_review.gd.uid b/tools/quell_review.gd.uid new file mode 100644 index 0000000..0e2649e --- /dev/null +++ b/tools/quell_review.gd.uid @@ -0,0 +1 @@ +uid://c24frdgf5sxxv diff --git a/tools/quell_review.tscn b/tools/quell_review.tscn new file mode 100644 index 0000000..28b7a7f --- /dev/null +++ b/tools/quell_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8quellreview"] + +[ext_resource type="Script" path="res://tools/quell_review.gd" id="1"] + +[node name="QuellReview" type="Node"] +script = ExtResource("1") diff --git a/tools/ringborke_benchmark.gd b/tools/ringborke_benchmark.gd new file mode 100644 index 0000000..cac0e5e --- /dev/null +++ b/tools/ringborke_benchmark.gd @@ -0,0 +1,69 @@ +extends Node3D +var stage: Node3D +var viewport: SubViewport +var camera: Camera3D +var figures: Array[Node3D] = [] +var results: Array = [] +func _ready() -> void: + call_deferred("run") +func run() -> void: + Soundscape.enabled = false + DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) + get_window().size = Vector2i(960,540) + viewport = SubViewport.new() + viewport.own_world_3d = true + viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS + viewport.msaa_3d = Viewport.MSAA_4X + add_child(viewport) + stage = Node3D.new() + viewport.add_child(stage) + var display := TextureRect.new() + display.texture = viewport.get_texture() + display.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) + display.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + add_child(display) + var env := WorldEnvironment.new() + env.environment=Environment.new() + preload("res://scripts/presentation/lighting.gd").configure(env.environment,true) + stage.add_child(env) + var light := DirectionalLight3D.new() + light.rotation_degrees=Vector3(-45,-30,0) + light.light_energy=1.3 + light.shadow_enabled=true + stage.add_child(light) + camera=Camera3D.new() + camera.projection=Camera3D.PROJECTION_ORTHOGONAL + stage.add_child(camera) + for resolution: Vector2i in [Vector2i(1920,1080),Vector2i(2560,1440)]: + viewport.size=resolution + for count: int in [1,30,90]: + for figure: Node3D in figures:figure.free() + figures.clear() + var columns: int = ceili(sqrt(count)) + for i: int in range(count): + var figure: Node3D = AssetLibrary.instantiate_fighter("w04") + figure.position=Vector3((i%columns-columns*.5)*2.2,0,(i/columns-columns*.5)*2.2) + stage.add_child(figure) + figures.append(figure) + camera.size=maxf(4,columns*2.5) + camera.position=Vector3(8,18,23) + camera.look_at(Vector3(0,.8,0)) + var times: Array[float]=[] + var started: int=Time.get_ticks_usec() + var previous: int=started + while Time.get_ticks_usec()-started < 8000000: + var elapsed: float = (Time.get_ticks_usec()-started)/1000000.0 + for i: int in range(figures.size()):figures[i].preview("walk",fmod(elapsed+i*.05,1.4)) + await get_tree().process_frame + var now: int=Time.get_ticks_usec() + if elapsed>2:times.append((now-previous)/1000.0) + previous=now + var total: float=0 + for t: float in times:total+=t + times.sort() + var record := {"resolution":str(resolution),"window_size":str(get_window().size),"render_size":str(viewport.get_texture().get_size()),"instances":count,"mean_frame_ms":total/times.size(),"p95_frame_ms":times[int(times.size()*.95)],"draw_calls":Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME),"video_memory_bytes":Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED),"fps":1000.0/(total/times.size())} + results.append(record) + print("RIG_BENCH: ",record) + var f:=FileAccess.open("res://docs/phase11-benchmark.json",FileAccess.WRITE) + f.store_string(JSON.stringify({"device":RenderingServer.get_video_adapter_name(),"renderer":RenderingServer.get_current_rendering_method(),"vsync":false,"msaa":"4x","render_target":"Fixed-size SubViewport independent of desktop DPI and window stretch","warmup_seconds":2,"sample_seconds":6,"scope":"Isolated animated characters; not a complete game benchmark; includes CPU and GPU frame pacing, not separately timed stages","results":results},"\t"));f.close() + await Soundscape.quit_game() diff --git a/tools/ringborke_benchmark.gd.uid b/tools/ringborke_benchmark.gd.uid new file mode 100644 index 0000000..82c5ef9 --- /dev/null +++ b/tools/ringborke_benchmark.gd.uid @@ -0,0 +1 @@ +uid://bvx31m2jbqswy diff --git a/tools/ringborke_benchmark.tscn b/tools/ringborke_benchmark.tscn new file mode 100644 index 0000000..0edd71b --- /dev/null +++ b/tools/ringborke_benchmark.tscn @@ -0,0 +1,4 @@ +[gd_scene load_steps=2 format=3] +[ext_resource type="Script" path="res://tools/ringborke_benchmark.gd" id="1"] +[node name="RingborkeBenchmark" type="Node3D"] +script = ExtResource("1") diff --git a/tools/ringborke_reel.gd b/tools/ringborke_reel.gd new file mode 100644 index 0000000..72732df --- /dev/null +++ b/tools/ringborke_reel.gd @@ -0,0 +1,33 @@ +extends Node +## Captures the actual imported character and in-game inspection controls. +var studio: Control +var frame: int = 0 +const FPS: float = 30.0 +const SCHEDULE = [["idle",2.5],["start",1.2],["walk",4.2],["stop",1.2],["attack_a",3.8],["attack_b",3.8],["hit",1.5],["ability",3.7],["death",3.4]] +func _ready() -> void: + get_window().size = Vector2i(1280,800) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + var main: Node3D = preload("res://scenes/main.tscn").instantiate() + add_child(main) + studio = main.hud.model_inspector + studio.show_model("w04") + studio._rotate = false + studio._clip_paused = true +func _process(_delta: float) -> void: + if studio == null:return + var time: float = frame/FPS + var cursor: float = 0.0 + for item: Array in SCHEDULE: + if time < cursor+float(item[1]): + var clip: String = item[0] + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i)==clip:studio._clip_selector.select(i) + var local_time: float = time-cursor + var length: float = studio._figure.clip_length(clip) + studio._clip_time = minf(local_time,length) if clip=="death" else fmod(local_time,length+.12) + studio._turntable.rotation.y = -.25+.16*sin(time*.28) + frame += 1 + return + cursor += item[1] + get_tree().quit() diff --git a/tools/ringborke_reel.gd.uid b/tools/ringborke_reel.gd.uid new file mode 100644 index 0000000..3d215fd --- /dev/null +++ b/tools/ringborke_reel.gd.uid @@ -0,0 +1 @@ +uid://c6adjdj8pgg3j diff --git a/tools/ringborke_reel.tscn b/tools/ringborke_reel.tscn new file mode 100644 index 0000000..5a0fab7 --- /dev/null +++ b/tools/ringborke_reel.tscn @@ -0,0 +1,4 @@ +[gd_scene load_steps=2 format=3] +[ext_resource type="Script" path="res://tools/ringborke_reel.gd" id="1"] +[node name="RingborkeReel" type="Node"] +script = ExtResource("1") diff --git a/tools/ringborke_review.gd b/tools/ringborke_review.gd new file mode 100644 index 0000000..08d881f --- /dev/null +++ b/tools/ringborke_review.gd @@ -0,0 +1,32 @@ +extends Node +## Real in-game inspector captures, animation reel and combat acceptance. +var main: Node3D +var captures := "res://docs/screenshots/phase11" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(8): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures+"/"+name+".png") +func run() -> void: + get_window().size = Vector2i(1600,1000) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + main.hud.model_inspector.show_model("w04") + var studio: Control = main.hud.model_inspector + studio._rotate = false + studio._clip_paused = true + studio._turntable.rotation.y = -.1 + await shot("ringborke-front") + studio._turntable.rotation.y = PI + await shot("ringborke-back") + studio._turntable.rotation.y = -.1 + for clip: String in ["walk","attack_a","attack_b","ability","hit","death"]: + for i: int in range(studio._clip_selector.item_count): + if studio._clip_selector.get_item_metadata(i) == clip:studio._clip_selector.select(i) + studio._clip_time = .9 if clip.begins_with("attack") else (1.8 if clip=="death" else .55) + await shot("pose-"+clip) + print("RINGBORKE_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/ringborke_review.gd.uid b/tools/ringborke_review.gd.uid new file mode 100644 index 0000000..1ba7384 --- /dev/null +++ b/tools/ringborke_review.gd.uid @@ -0,0 +1 @@ +uid://byw4ih1wuf3m4 diff --git a/tools/ringborke_review.tscn b/tools/ringborke_review.tscn new file mode 100644 index 0000000..6925e8c --- /dev/null +++ b/tools/ringborke_review.tscn @@ -0,0 +1,4 @@ +[gd_scene load_steps=2 format=3] +[ext_resource type="Script" path="res://tools/ringborke_review.gd" id="1"] +[node name="RingborkeReview" type="Node"] +script = ExtResource("1") diff --git a/tools/screenshot.gd b/tools/screenshot.gd new file mode 100644 index 0000000..77baec9 --- /dev/null +++ b/tools/screenshot.gd @@ -0,0 +1,94 @@ +extends Node +## UI smoke check with the real main scene and ordinary economic commands. +## Run: godot --path . res://tools/screenshot.tscn + +const OUT_DIR := "res://docs/screenshots" + + +func _ready() -> void: + get_tree().create_timer(25.0).timeout.connect(func(): + printerr("FAIL: graphical smoke check did not finish.") + get_tree().quit(1)) + DirAccess.make_dir_recursive_absolute(OUT_DIR) + var main: Node3D = load("res://scenes/main.tscn").instantiate() + add_child(main) + await _wait(1.2) + _capture("menu-overlay.png") + main.hud._overlay_action.pressed.emit() + main.hud._starter_button.pressed.emit() + await _wait(0.5) + assert(GameState.phase == GameState.Phase.BUILD) + assert(EconomyManager.get_team(0).gold == 40) + assert(EconomyManager.get_team(0).roster.size() == 3) + main.selected_uid = EconomyManager.get_team(0).roster[0].uid + main.hud.selected_uid = main.selected_uid + main._update_selection_visuals() + await _wait(0.3) + _capture("build-phase.png") + main.hud._pause_button.grab_focus() + _key(KEY_SPACE) + await _wait(3.0) + assert(GameState.phase == GameState.Phase.COMBAT) + _capture("combat-phase.png") + main.hud._pause_button.pressed.emit() + var paused_time: float = main.battle.elapsed + await _wait(0.25) + assert(is_equal_approx(main.battle.elapsed, paused_time)) + main.hud._pause_button.pressed.emit() + _key(KEY_TAB) + assert(main.viewed_team == 1) + # Finish using real fixed combat steps; no balance values are modified. + WaveManager.set_physics_process(false) + for _step in range(5400): + if GameState.phase != GameState.Phase.COMBAT: + break + WaveManager.advance(1.0 / 60.0) + assert(GameState.phase == GameState.Phase.RESULTS) + main.hud._ready_button.pressed.emit() + assert(GameState.wave == 2 and GameState.phase == GameState.Phase.BUILD) + main.hud._front_button.pressed.emit() + await _wait(0.2) + var cell_point: Vector2 = main.camera.unproject_position(Vector3(-14, 0, 7)) + main.hud._shop_buttons["g01"].pressed.emit() + # Route through Godot's real input path, including plane picking and grid snap. + var motion := InputEventMouseMotion.new() + motion.position = cell_point + get_viewport().push_input(motion, true) + await get_tree().process_frame + var click := InputEventMouseButton.new() + click.position = cell_point + click.button_index = MOUSE_BUTTON_LEFT + click.pressed = true + get_viewport().push_input(click, true) + await get_tree().process_frame + click = click.duplicate() + click.pressed = false + get_viewport().push_input(click, true) + await get_tree().process_frame + assert(EconomyManager.get_team(0).roster.size() == 4) + assert(EconomyManager.get_team(0).roster[3].cell == Vector2i(0, 7)) + main.hud._undo.pressed.emit() + assert(EconomyManager.get_team(0).roster.size() == 3) + print("PASS: HUD start, formation, keyboard shortcuts with button focus, combat, pause, front switch, next wave, mouse placement and undo.") + await Soundscape.quit_game(0) + + +func _wait(seconds: float) -> void: + await get_tree().create_timer(seconds).timeout + + +func _key(keycode: int) -> void: + var event := InputEventKey.new() + event.keycode = keycode + event.pressed = true + get_viewport().push_input(event, true) + event = event.duplicate() + event.pressed = false + get_viewport().push_input(event, true) + + +func _capture(file_name: String) -> void: + var image: Image = get_viewport().get_texture().get_image() + var path: String = OUT_DIR + "/" + file_name + image.save_png(path) + print("Saved ", path) diff --git a/tools/screenshot.gd.uid b/tools/screenshot.gd.uid new file mode 100644 index 0000000..92e0869 --- /dev/null +++ b/tools/screenshot.gd.uid @@ -0,0 +1 @@ +uid://b4pftj0dsg0m7 diff --git a/tools/screenshot.tscn b/tools/screenshot.tscn new file mode 100644 index 0000000..f93392c --- /dev/null +++ b/tools/screenshot.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/screenshot.gd" id="1_shot"] + +[node name="Screenshot" type="Node"] +script = ExtResource("1_shot") diff --git a/tools/ui_review.gd b/tools/ui_review.gd new file mode 100644 index 0000000..0cb3331 --- /dev/null +++ b/tools/ui_review.gd @@ -0,0 +1,22 @@ +extends Node +## Capture the redesigned title menu and in-game HUD. +var main: Node3D +var captures := "res://docs/screenshots/phase13" +func _ready() -> void: + call_deferred("run") +func shot(name: String) -> void: + for n: int in range(10): await get_tree().process_frame + await RenderingServer.frame_post_draw + get_viewport().get_texture().get_image().save_png(captures + "/" + name + ".png") +func run() -> void: + get_window().size = Vector2i(1920, 1080) + Soundscape.enabled = false + WaveManager.set_physics_process(false) + main = preload("res://scenes/main.tscn").instantiate() + add_child(main) + await shot("menu") + main.hud._overlay_action.pressed.emit() + main.hud._starter_button.pressed.emit() + await shot("build") + print("UI_REVIEW_PASS") + await Soundscape.quit_game() diff --git a/tools/ui_review.gd.uid b/tools/ui_review.gd.uid new file mode 100644 index 0000000..23b81bc --- /dev/null +++ b/tools/ui_review.gd.uid @@ -0,0 +1 @@ +uid://cw6qfhk2hvbv2 diff --git a/tools/ui_review.tscn b/tools/ui_review.tscn new file mode 100644 index 0000000..972931f --- /dev/null +++ b/tools/ui_review.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8uireview13"] + +[ext_resource type="Script" path="res://tools/ui_review.gd" id="1"] + +[node name="UiReview" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_ability_events.gd b/tools/verify_ability_events.gd new file mode 100644 index 0000000..6800fd3 --- /dev/null +++ b/tools/verify_ability_events.gd @@ -0,0 +1,115 @@ +extends Node +## Exercise real ability producers, battle clocks and imported character poses. +const BattleScript = preload("res://scripts/combat/battle_controller.gd") +const STEP: float = 1.0 / 60.0 +var checks: int = 0 +var failures: Array[String] = [] +var protection_restarted: bool = false + +func _ready() -> void: + WaveManager.set_physics_process(false) + call_deferred("run") + +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("ABILITY_EVENT_FAIL: ", label) + +func run() -> void: + for speed: int in [1, 2]: + verify_battle(speed) + check(checks == 32, "Both battle-clock scenarios complete every assertion") + var file := FileAccess.open("res://docs/ability-animation-verification.json", FileAccess.WRITE) + file.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + file.close() + print("ABILITY_EVENT_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) + +func verify_battle(speed: int) -> void: + protection_restarted = false + GameState.reset_match() + GameState.speed = speed + var battle: BattleController = BattleScript.new() + add_child(battle) + battle.set_process(false) + WaveManager.attach_battle(battle) + var roster: Array = [ + {"type_id": "g04", "uid": 1, "cell": Vector2i(2, 3)}, + {"type_id": "w10", "uid": 2, "cell": Vector2i(3, 3)}, + {"type_id": "w04", "uid": 3, "cell": Vector2i(2, 4)}] + battle.show_formation([roster, []]) + GameState.set_phase(GameState.Phase.BUILD) + battle._process(.1) + var bastion: CombatUnit = battle.units[0] + check(bastion.ability_pose_flash == 0 and bastion._model.current_clip == "idle", + "%dx: formation does not activate the opening protection pose" % speed) + var enemy: Dictionary = DataCatalog.get_attackers(1)[0] + enemy.speed = 0.0 + enemy.damage = 0.0 + battle.begin_battle([roster, []], [[enemy], []], 1) + GameState.set_phase(GameState.Phase.COMBAT) + bastion = battle.units[0] + var healer: CombatUnit = battle.units[1] + var ringborke: CombatUnit = battle.units[2] + for index: int in range(battle.units.size()): + var unit: CombatUnit = battle.units[index] + unit.data.speed = 0.0 + unit.position = Vector3(-9, 0, float(index) if not unit.is_attacker else -30.0) + unit.refresh_visuals() + check(bastion.ability_pose_flash == 0, "%dx: battle setup waits for a combat step" % speed) + WaveManager._physics_process(STEP) + check(bastion.ability_pose_flash > 0 and bastion._model.current_clip == "ability", + "%dx: first combat step starts Basaltbastion's imported protection clip" % speed) + check(is_equal_approx(bastion.damage_reduction(), .25), "%dx: opening reduction remains 25%%" % speed) + var pose_at: float = bastion._model.player.current_animation_position + var elapsed: float = battle.elapsed + var flash: float = bastion.ability_pose_flash + GameState.paused = true + for frame: int in range(30): + WaveManager._physics_process(STEP) + check(is_equal_approx(battle.elapsed, elapsed) and is_equal_approx(bastion.ability_pose_flash, flash) + and is_equal_approx(bastion._model.player.current_animation_position, pose_at), + "%dx: pause freezes combat, activation pulse and skeletal playback" % speed) + GameState.paused = false + for frame: int in range(30): + WaveManager._physics_process(STEP) + check(is_equal_approx(battle.elapsed - elapsed, .5 * speed) + and absf(bastion._model.player.current_animation_position - pose_at - .5 * speed) < .0001, + "%dx: skeletal protection follows the fixed battle clock" % speed) + advance_until(battle, 3.0) + check(bastion.ability_pose_flash == 0 and bastion._model.current_clip == "idle", + "%dx: protection completes without repeating" % speed) + bastion.hp = bastion.max_hp - 150.0 + ringborke.hp = ringborke.max_hp - 150.0 + advance_until(battle, 4.0) + check(is_equal_approx(bastion.hp, bastion.max_hp - 70.0) + and is_equal_approx(ringborke.hp, ringborke.max_hp - 70.0), + "%dx: Quellgeflecht still heals each wounded recipient by 80 HP" % speed) + check(healer.ability_pose_flash > 0 and healer._model.current_clip == "ability", + "%dx: the caster starts its own multi-heal animation" % speed) + for recipient: CombatUnit in [bastion, ringborke]: + check(recipient.ability_flash > 0 and recipient._pulse.visible, + "%dx: %s retains the received healing effect" % [speed, recipient.data.id]) + check(recipient.ability_pose_flash == 0 and recipient._model.current_clip == "idle" + and recipient._model._ability_time < 0, + "%dx: %s does not cast its own ability when healed" % [speed, recipient.data.id]) + advance_until(battle, 5.0) + check(ringborke.ability_pose_flash > 0 and ringborke._model.current_clip == "ability" + and is_equal_approx(ringborke.hp, ringborke.max_hp), + "%dx: a later self-heal still activates after receiving someone else's healing" % speed) + advance_until(battle, 10.1) + check(is_equal_approx(bastion.damage_reduction(), .10), "%dx: later reduction remains 10%%" % speed) + check(bastion.ability_pose_flash == 0 and bastion._model.current_clip == "idle" + and bastion._model._ability_time < 0 and not protection_restarted, + "%dx: passive expiry and repeated external healing do not restart protection" % speed) + battle.free() + WaveManager.battle = null + +func advance_until(battle: BattleController, seconds: float) -> void: + while battle.elapsed < seconds - .000001 and not battle.finished: + WaveManager._physics_process(STEP) + if battle.elapsed > 3.0: + var bastion: CombatUnit = battle.units[0] + protection_restarted = protection_restarted or bastion.ability_pose_flash > 0 \ + or bastion._model.current_clip == "ability" or bastion._model._ability_time >= 0 diff --git a/tools/verify_ability_events.gd.uid b/tools/verify_ability_events.gd.uid new file mode 100644 index 0000000..1bc0296 --- /dev/null +++ b/tools/verify_ability_events.gd.uid @@ -0,0 +1 @@ +uid://q1a1epux77n diff --git a/tools/verify_ability_events.tscn b/tools/verify_ability_events.tscn new file mode 100644 index 0000000..0b95a55 --- /dev/null +++ b/tools/verify_ability_events.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/verify_ability_events.gd" id="1"] + +[node name="VerifyAbilityEvents" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_arbeiter.gd b/tools/verify_arbeiter.gd new file mode 100644 index 0000000..f7ec2b7 --- /dev/null +++ b/tools/verify_arbeiter.gd @@ -0,0 +1,77 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ", label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("worker") + var b: Node3D = AssetLibrary.instantiate_fighter("worker") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count() == 27, "27 imported bones") + check(a.player != b.player and a.skeleton != b.skeleton, "independent skeleton and playback") + for clip: String in ["idle", "start", "walk", "stop", "strike", "pickup", "deposit", "return", "hit", "death"]: + check(a.clips.has(clip), "imported clip " + clip) + check(a.clip_length(clip) > .25, "clip duration " + clip) + var hand: int = a.skeleton.find_bone("Hand.L") + var rest: Quaternion = b.skeleton.get_bone_pose_rotation(hand) + a.preview("strike", .80) + check(a.skeleton.get_bone_pose_rotation(hand).angle_to(rest) > .05, "strike deforms weighted arm") + a.preview("pickup", .40) + var spine: int = a.skeleton.find_bone("Spine") + check(a.skeleton.get_bone_pose_rotation(spine).angle_to(Quaternion.IDENTITY) > .05, "pickup crouches spine") + a.preview("deposit", .60) + check(a.current_clip == "deposit" or a.clips.has("deposit"), "deposit clip available") + a.preview("idle", 0) + check(a.skeleton.get_bone_pose_rotation(hand).is_equal_approx(b.skeleton.get_bone_pose_rotation(hand)), "idle restores hands after work") + # Work cycle advances through tool contact, gather, deposit and return. + var seen: Dictionary = {} + for i in range(400): + a.update_work(1.0 / 60, 0.0) + seen[a.current_clip] = true + check(seen.has("strike") and seen.has("pickup") and seen.has("deposit") and seen.has("return"), "full work cycle plays") + check(seen.has("idle"), "idle gap between work steps") + # Render cadence and worker phase offsets must not duplicate contact effects. + for fps: int in [30, 60, 144]: + for phase: float in [0.0, .83, 1.66]: + var worker: Node3D = AssetLibrary.instantiate_fighter("worker") + add_child(worker) + var contacts: int = 0 + var extra_contact: bool = false + var elapsed: float = 0.0 + var duration: float = worker.cycle_length() * 3.0 + while elapsed < duration - .000001: + var step: float = minf(1.0 / fps, duration - elapsed) + worker.update_work(step, phase) + elapsed += step + if worker.consume_strike_contact(): + contacts += 1 + worker.update_work(0.0, phase) + extra_contact = extra_contact or worker.consume_strike_contact() + check(contacts == 3 and not extra_contact, "%d FPS / phase %.2f: one contact per cycle, none while paused (contacts=%d, extra=%s)" % [fps, phase, contacts, extra_contact]) + worker.free() + # Contact frame is on the strike clip, before follow-through. + a.preview("strike", 0) + var contact: float = .62 * a.clip_length("strike") + a.preview("strike", contact) + check(absf(a.player.current_animation_position - contact) < .02, "strike contact time is authored") + var core: Node3D = AssetLibrary.instantiate_fighter("core_team0") + add_child(core) + check(core.has_method("set_core_health") and core.has_method("trigger_activate"), "core exposes activation and health") + core.trigger_activate() + core.set_core_health(.4) + core.pose(0.5, false, 0, 0, 0, 1.0 / 60) + check(true, "core pose accepts damage state") + core.free() + a.free() + b.free() + var f := FileAccess.open("res://docs/phase12-rig-verification.json", FileAccess.WRITE) + f.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + f.close() + print("RIG_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_arbeiter.gd.uid b/tools/verify_arbeiter.gd.uid new file mode 100644 index 0000000..833979d --- /dev/null +++ b/tools/verify_arbeiter.gd.uid @@ -0,0 +1 @@ +uid://cho61shwyias7 diff --git a/tools/verify_arbeiter.py b/tools/verify_arbeiter.py new file mode 100644 index 0000000..8bd8f1d --- /dev/null +++ b/tools/verify_arbeiter.py @@ -0,0 +1,59 @@ +"""Validate the portable skin/animation asset, independent of Godot's wrapper.""" +from pathlib import Path +import json, math, sys +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from verify_phase4_glb import GLB, topology +p = Path(__file__).resolve().parents[1] +g = GLB(p / 'assets/characters/arbeiter.glb') +d = g.doc +checks = [] + +def check(v, msg): + assert v, msg + checks.append(msg) + +check(len(d['skins']) == 1, 'one portable skin') +check(len(d['skins'][0]['joints']) == 27, '27 distinct joint bindings') +expected = {'idle', 'start', 'walk', 'stop', 'strike', 'pickup', 'deposit', 'return', 'hit', 'death'} +check({a['name'] for a in d['animations']} == expected, 'ten complete clips') +weighted = 0 +total = 0 +max_error = 0 +for m in d['meshes']: + for q in m['primitives']: + attr = q['attributes'] + vertices = g.accessor(attr['POSITION']) + indices = [x[0] for x in g.accessor(q['indices'])] + t = topology(vertices, [indices[i:i + 3] for i in range(0, len(indices), 3)]) + check(t['closed'] and t['signed_volume'] > 0 and t['degenerate_triangles'] == 0, 'closed outward geometry ' + d['materials'][q['material']]['name']) + check(all(x in attr for x in ('JOINTS_0', 'WEIGHTS_0', 'POSITION', 'NORMAL', 'TEXCOORD_0')), 'skin, normals and UVs') + joints = g.accessor(attr['JOINTS_0']) + weights = g.accessor(attr['WEIGHTS_0']) + normals = g.accessor(attr['NORMAL']) + for js, ws, n in zip(joints, weights, normals): + assert all(0 <= j < 27 for j in js) + assert all(math.isfinite(w) and 0 <= w <= 1 for w in ws) + max_error = max(max_error, abs(sum(ws) - 1)) + weighted += sum(w > .001 for w in ws) > 1 + total += 1 + assert all(math.isfinite(v) for v in n) +check(max_error < .0001, 'all vertex weights normalized') +check(weighted / total > .10, 'flexible tissue has blended joints') +for a in d['animations']: + check(len(a['channels']) > 5, a['name'] + ' animates multiple joints') + for samp in a['samplers']: + times = [v[0] for v in g.accessor(samp['input'])] + assert times == sorted(times) and times[0] >= 0 + assert all(math.isfinite(x) for row in g.accessor(samp['output']) for x in row) +report = { + 'checks': len(checks), + 'failures': [], + 'vertices': total, + 'blended_vertices': weighted, + 'blended_percent': round(weighted / total * 100, 2), + 'max_weight_sum_error': max_error, + 'clips': sorted(expected), + 'bones': 27, +} +(p / 'docs/phase12-skin-audit.json').write_text(json.dumps(report, indent=2) + '\n') +print(report) diff --git a/tools/verify_arbeiter.tscn b/tools/verify_arbeiter.tscn new file mode 100644 index 0000000..d87e91d --- /dev/null +++ b/tools/verify_arbeiter.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8arbeiterverify"] + +[ext_resource type="Script" path="res://tools/verify_arbeiter.gd" id="1"] + +[node name="VerifyArbeiter" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_basalt.gd b/tools/verify_basalt.gd new file mode 100644 index 0000000..880cae7 --- /dev/null +++ b/tools/verify_basalt.gd @@ -0,0 +1,46 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ", label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("g04") + var b: Node3D = AssetLibrary.instantiate_fighter("g04") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count() == 17, "17 imported bones") + check(a.player != b.player and a.skeleton != b.skeleton, "independent skeleton and playback") + for clip: String in ["idle", "start", "walk", "stop", "attack_a", "attack_b", "hit", "ability", "death"]: + check(a.clips.has(clip), "imported clip " + clip) + check(a.clip_length(clip) > .3, "clip duration " + clip) + var thigh: int = a.skeleton.find_bone("Thigh.L") + var rest: Quaternion = b.skeleton.get_bone_pose_rotation(thigh) + a.preview("walk", .40) + check(a.skeleton.get_bone_pose_rotation(thigh).angle_to(rest) > .05, "walking deforms weighted leg") + a.preview("attack_a", .90) + var hand: int = a.skeleton.find_bone("Hand.L") + check(a.skeleton.get_bone_pose_rotation(hand).angle_to(rest) > .05, "left attack moves fist") + a.preview("ability", .50) + check(a.current_clip == "ability" or a.clips.has("ability"), "defensive ability clip") + a.preview("idle", 0) + check(a.skeleton.get_bone_pose_rotation(thigh).is_equal_approx(b.skeleton.get_bone_pose_rotation(thigh)), "idle restores pose") + a.update_combat(1.0 / 60, 0, true, .6, 0, 0, 0, true) + check(a.current_clip == "attack_a", "combat uses left attack") + a.update_combat(1.0 / 60, 0, true, 0, 1, 0, 0, true) + check(absf(a.player.current_animation_position - .9) < .001, "damage frame matches contact") + a.update_combat(1.0 / 60, 0, true, .65, 1, 0, 0, true) + check(a.current_clip == "attack_b", "alternating right attack") + a.update_combat(1.0 / 60, 0, false, 0, 1, 0, 0, false) + check(a.dead and a.current_clip == "death", "death clip") + a.free() + b.free() + var f := FileAccess.open("res://docs/phase15-rig-verification.json", FileAccess.WRITE) + f.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + f.close() + print("RIG_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_basalt.gd.uid b/tools/verify_basalt.gd.uid new file mode 100644 index 0000000..994cafb --- /dev/null +++ b/tools/verify_basalt.gd.uid @@ -0,0 +1 @@ +uid://c6eib6iun6obu diff --git a/tools/verify_basalt.tscn b/tools/verify_basalt.tscn new file mode 100644 index 0000000..9d0fffd --- /dev/null +++ b/tools/verify_basalt.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8basaltverify"] + +[ext_resource type="Script" path="res://tools/verify_basalt.gd" id="1"] + +[node name="VerifyBasalt" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_funken.gd b/tools/verify_funken.gd new file mode 100644 index 0000000..841941f --- /dev/null +++ b/tools/verify_funken.gd @@ -0,0 +1,62 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ", label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("g05") + var b: Node3D = AssetLibrary.instantiate_fighter("g05") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count() == 26, "26 imported bones") + check(a.player != b.player and a.skeleton != b.skeleton, "independent skeleton and playback") + for clip: String in ["idle", "start", "walk", "stop", "attack_a", "attack_b", "hit", "ability", "death"]: + check(a.clips.has(clip), "imported clip " + clip) + check(a.clip_length(clip) > .3, "clip duration " + clip) + var arm: int = a.skeleton.find_bone("UpperArm.R") + var weapon: int = a.skeleton.find_bone("Weapon") + var crystal: int = a.skeleton.find_bone("Crystal") + var bolt: int = a.skeleton.find_bone("Bolt") + var thigh: int = a.skeleton.find_bone("Thigh.L") + check(arm >= 0 and weapon >= 0 and crystal >= 0 and bolt >= 0, "lance rig joints present") + check(thigh >= 0, "has legs") + check(a.attack_cycle == ["attack_a", "attack_b", "attack_a", "ability"], "four-hit lance cycle") + var rest_thigh: Quaternion = b.skeleton.get_bone_pose_rotation(thigh) + var rest_weapon: Quaternion = b.skeleton.get_bone_pose_rotation(weapon) + var rest_crystal: Quaternion = b.skeleton.get_bone_pose_rotation(crystal) + a.preview("walk", .40) + check(a.skeleton.get_bone_pose_rotation(thigh).angle_to(rest_thigh) > .1, "walk strides legs") + a.preview("attack_a", .90) + check(a.skeleton.get_bone_pose_rotation(weapon).angle_to(rest_weapon) > .02, "free shot aims lance") + check(a.skeleton.get_bone_pose_rotation(arm).angle_to(b.skeleton.get_bone_pose_rotation(arm)) > .01, "shot settles arm on lance") + a.preview("ability", .90) + check(a.skeleton.get_bone_pose_rotation(crystal).angle_to(rest_crystal) > .2, "charged shot spins crystal") + a.preview("attack_a", .98) + check(a.skeleton.get_bone_pose_position(bolt).distance_to(b.skeleton.get_bone_pose_position(bolt)) > .01, "breech slides after contact") + b.preview("idle", 0) + a.preview("idle", 0) + check(a.skeleton.get_bone_pose_rotation(weapon).is_equal_approx(b.skeleton.get_bone_pose_rotation(weapon)), "idle restores lance hold") + a.update_combat(1.0 / 60, 0, true, .6, 0, 0, 0, true) + check(a.current_clip == "attack_a", "combat free shot") + a.update_combat(1.0 / 60, 0, true, 0, 1, 0, 0, true) + check(absf(a.player.current_animation_position - .9) < .001, "contact frame at 0.90 s") + a.update_combat(1.0 / 60, 0, true, .65, 1, 0, 0, true) + check(a.current_clip == "attack_b", "alternating braced shot") + a.update_combat(1.0 / 60, 0, true, .65, 2, 0, 0, true) + check(a.current_clip == "attack_a", "third shot free again") + a.update_combat(1.0 / 60, 0, true, .65, 3, 0, 0, true) + check(a.current_clip == "ability", "fourth hit is the charged lance shot") + a.update_combat(1.0 / 60, 0, false, 0, 1, 0, 0, false) + check(a.dead and a.current_clip == "death", "death clip") + a.free() + b.free() + var f := FileAccess.open("res://docs/phase18-rig-verification.json", FileAccess.WRITE) + f.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + f.close() + print("RIG_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_funken.gd.uid b/tools/verify_funken.gd.uid new file mode 100644 index 0000000..ef2ac5b --- /dev/null +++ b/tools/verify_funken.gd.uid @@ -0,0 +1 @@ +uid://dca7vfgtojdla diff --git a/tools/verify_funken.tscn b/tools/verify_funken.tscn new file mode 100644 index 0000000..371cf27 --- /dev/null +++ b/tools/verify_funken.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8funkenverify"] + +[ext_resource type="Script" path="res://tools/verify_funken.gd" id="1"] + +[node name="VerifyFunken" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_funkenlanze.py b/tools/verify_funkenlanze.py new file mode 100644 index 0000000..20ef821 --- /dev/null +++ b/tools/verify_funkenlanze.py @@ -0,0 +1,63 @@ +"""Validate the portable Funkenlanze skin/animation asset, independent of Godot.""" +from pathlib import Path +import json, math, sys +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from verify_phase4_glb import GLB, topology +p = Path(__file__).resolve().parents[1] +g = GLB(p / 'assets/characters/funkenlanze.glb') +d = g.doc +checks = [] + +def check(v, msg): + assert v, msg + checks.append(msg) + +check(len(d['skins']) == 1, 'one portable skin') +check(len(d['skins'][0]['joints']) == 26, '26 distinct joint bindings') +expected = {'idle', 'start', 'walk', 'stop', 'attack_a', 'attack_b', 'hit', 'ability', 'death'} +check({a['name'] for a in d['animations']} == expected, 'nine complete clips') +weighted = 0 +total = 0 +max_error = 0 +for m in d['meshes']: + for q in m['primitives']: + attr = q['attributes'] + vertices = g.accessor(attr['POSITION']) + indices = [x[0] for x in g.accessor(q['indices'])] + t = topology(vertices, [indices[i:i + 3] for i in range(0, len(indices), 3)]) + name = d['materials'][q['material']]['name'] + check(t['closed'] and t['signed_volume'] > 0 and t['degenerate_triangles'] == 0, + 'closed outward geometry ' + name) + check(all(x in attr for x in ('JOINTS_0', 'WEIGHTS_0', 'POSITION', 'NORMAL', 'TEXCOORD_0')), + 'skin, normals and UVs') + joints = g.accessor(attr['JOINTS_0']) + weights = g.accessor(attr['WEIGHTS_0']) + normals = g.accessor(attr['NORMAL']) + for js, ws, n in zip(joints, weights, normals): + assert all(0 <= j < 26 for j in js) + assert all(math.isfinite(w) and 0 <= w <= 1 for w in ws) + max_error = max(max_error, abs(sum(ws) - 1)) + weighted += sum(w > .001 for w in ws) > 1 + total += 1 + assert all(math.isfinite(v) for v in n) +check(max_error < .0001, 'all vertex weights normalized') +# Mineral plates stay single-weighted; continuous limb/torso cores carry the blend zones. +check(weighted / total > .08, 'joint zones have blended vertices') +for a in d['animations']: + check(len(a['channels']) > 5, a['name'] + ' animates multiple joints') + for samp in a['samplers']: + times = [v[0] for v in g.accessor(samp['input'])] + assert times == sorted(times) and times[0] >= 0 + assert all(math.isfinite(x) for row in g.accessor(samp['output']) for x in row) +report = { + 'checks': len(checks), + 'failures': [], + 'vertices': total, + 'blended_vertices': weighted, + 'blended_percent': round(weighted / total * 100, 2), + 'max_weight_sum_error': max_error, + 'clips': sorted(expected), + 'bones': 26, +} +(p / 'docs/phase18-skin-audit.json').write_text(json.dumps(report, indent=2) + '\n') +print(report) diff --git a/tools/verify_glasballiste.py b/tools/verify_glasballiste.py new file mode 100644 index 0000000..98004c7 --- /dev/null +++ b/tools/verify_glasballiste.py @@ -0,0 +1,63 @@ +"""Validate the portable Glasballiste skin/animation asset, independent of Godot.""" +from pathlib import Path +import json, math, sys +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from verify_phase4_glb import GLB, topology +p = Path(__file__).resolve().parents[1] +g = GLB(p / 'assets/characters/glasballiste.glb') +d = g.doc +checks = [] + +def check(v, msg): + assert v, msg + checks.append(msg) + +check(len(d['skins']) == 1, 'one portable skin') +check(len(d['skins'][0]['joints']) == 20, '20 distinct joint bindings') +expected = {'idle', 'start', 'walk', 'stop', 'attack_a', 'attack_b', 'hit', 'ability', 'death'} +check({a['name'] for a in d['animations']} == expected, 'nine complete clips') +weighted = 0 +total = 0 +max_error = 0 +for m in d['meshes']: + for q in m['primitives']: + attr = q['attributes'] + vertices = g.accessor(attr['POSITION']) + indices = [x[0] for x in g.accessor(q['indices'])] + t = topology(vertices, [indices[i:i + 3] for i in range(0, len(indices), 3)]) + name = d['materials'][q['material']]['name'] + check(t['closed'] and t['signed_volume'] > 0 and t['degenerate_triangles'] == 0, + 'closed outward geometry ' + name) + check(all(x in attr for x in ('JOINTS_0', 'WEIGHTS_0', 'POSITION', 'NORMAL', 'TEXCOORD_0')), + 'skin, normals and UVs') + joints = g.accessor(attr['JOINTS_0']) + weights = g.accessor(attr['WEIGHTS_0']) + normals = g.accessor(attr['NORMAL']) + for js, ws, n in zip(joints, weights, normals): + assert all(0 <= j < 20 for j in js) + assert all(math.isfinite(w) and 0 <= w <= 1 for w in ws) + max_error = max(max_error, abs(sum(ws) - 1)) + weighted += sum(w > .001 for w in ws) > 1 + total += 1 + assert all(math.isfinite(v) for v in n) +check(max_error < .0001, 'all vertex weights normalized') +# Armor stays single-weighted; joint sleeves, bending crystal limbs and the draw cable carry the blends. +check(weighted / total > .08, 'joint zones have blended vertices') +for a in d['animations']: + check(len(a['channels']) > 5, a['name'] + ' animates multiple joints') + for samp in a['samplers']: + times = [v[0] for v in g.accessor(samp['input'])] + assert times == sorted(times) and times[0] >= 0 + assert all(math.isfinite(x) for row in g.accessor(samp['output']) for x in row) +report = { + 'checks': len(checks), + 'failures': [], + 'vertices': total, + 'blended_vertices': weighted, + 'blended_percent': round(weighted / total * 100, 2), + 'max_weight_sum_error': max_error, + 'clips': sorted(expected), + 'bones': 20, +} +(p / 'docs/phase19-skin-audit.json').write_text(json.dumps(report, indent=2) + '\n') +print(report) diff --git a/tools/verify_glass.gd b/tools/verify_glass.gd new file mode 100644 index 0000000..62c1099 --- /dev/null +++ b/tools/verify_glass.gd @@ -0,0 +1,88 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ", label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("g06") + var b: Node3D = AssetLibrary.instantiate_fighter("g06") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count() == 20, "20 imported bones") + check(a.player != b.player and a.skeleton != b.skeleton, "independent skeleton and playback") + for clip: String in ["idle", "start", "walk", "stop", "attack_a", "attack_b", "hit", "ability", "death"]: + check(a.clips.has(clip), "imported clip " + clip) + check(a.clip_length(clip) > .3, "clip duration " + clip) + var weapon: int = a.skeleton.find_bone("Weapon") + var draw: int = a.skeleton.find_bone("Draw") + var bolt: int = a.skeleton.find_bone("Bolt") + var quarrel: int = a.skeleton.find_bone("Quarrel") + var gear: int = a.skeleton.find_bone("Gear") + var tip: int = a.skeleton.find_bone("LimbTip.L") + var thigh: int = a.skeleton.find_bone("Thigh.L") + var foot: int = a.skeleton.find_bone("Foot.L") + check(weapon >= 0 and draw >= 0 and bolt >= 0 and quarrel >= 0 and gear >= 0 and tip >= 0, "ballista rig joints present") + check(thigh >= 0 and a.skeleton.find_bone("Tarsus.L") >= 0 and foot >= 0, "digitigrade legs with feet") + check(a.skeleton.find_bone("Head") < 0 and a.skeleton.find_bone("UpperArm.L") < 0, "headless walker without arms") + check(a.skeleton.find_bone("Spine") >= 0, "turret joint receives the hit overlay") + check(a.attack_cycle == ["attack_a", "attack_b", "attack_a", "ability"], "four-hit ballista cycle") + var rest_tip: Quaternion = b.skeleton.get_bone_pose_rotation(tip) + var rest_gear: Quaternion = b.skeleton.get_bone_pose_rotation(gear) + var rest_quarrel: Quaternion = b.skeleton.get_bone_pose_rotation(quarrel) + var rest_draw: Vector3 = b.skeleton.get_bone_pose_position(draw) + var rest_bolt: Vector3 = b.skeleton.get_bone_pose_position(bolt) + # Touchdown (foot ahead) and lift-off (foot behind) swing the thigh through the stride. + a.preview("walk", 0) + var reach: Quaternion = a.skeleton.get_bone_pose_rotation(thigh) + a.preview("walk", .70) + check(a.skeleton.get_bone_pose_rotation(thigh).angle_to(reach) > .1, "walk strides legs") + # Left foot is planted from 0.10 s to 0.30 s: it slides back exactly with the 0.52 m stride. + a.preview("walk", .10) + var planted: Vector3 = a.skeleton.get_bone_global_pose(foot).origin + a.preview("walk", .30) + var later: Vector3 = a.skeleton.get_bone_global_pose(foot).origin + check(absf((planted.z - later.z) - .52 / 1.2 * .2) < .003, "planted foot travels with the stride") + check(absf(planted.y - later.y) < .002 and absf(planted.x - later.x) < .002, "planted foot keeps ground contact") + a.preview("walk", .90) + check(a.skeleton.get_bone_global_pose(foot).origin.y > planted.y + .05, "swing foot lifts off") + a.preview("attack_a", .90) + check(a.skeleton.get_bone_pose_position(draw).distance_to(rest_draw) < .01, "string still cocked at contact") + a.preview("attack_a", .95) + check(a.skeleton.get_bone_pose_position(draw).distance_to(rest_draw) > .2, "string snaps forward on release") + check(a.skeleton.get_bone_pose_rotation(tip).angle_to(rest_tip) > .1, "crystal limbs spring forward") + a.preview("attack_a", .97) + check(a.skeleton.get_bone_pose_scale(bolt).x < .05, "bolt leaves the rail after contact") + a.preview("attack_a", 1.10) + check(a.skeleton.get_bone_pose_rotation(gear).angle_to(rest_gear) > .3, "crank winds during reload") + a.preview("attack_a", 1.30) + check(a.skeleton.get_bone_pose_scale(bolt).x > .99 and a.skeleton.get_bone_pose_position(bolt).distance_to(rest_bolt) < .005, "reloaded for the next shot") + a.preview("ability", .80) + check(a.skeleton.get_bone_pose_rotation(quarrel).angle_to(rest_quarrel) > .1, "charged shot spins quarrel") + check(a.skeleton.get_bone_pose_scale(quarrel).x > 1.05, "charged quarrel swells") + b.preview("idle", 0) + a.preview("idle", 0) + check(a.skeleton.get_bone_pose_rotation(weapon).is_equal_approx(b.skeleton.get_bone_pose_rotation(weapon)), "idle restores ballista hold") + a.update_combat(1.0 / 60, 0, true, .6, 0, 0, 0, true) + check(a.current_clip == "attack_a", "combat free shot") + a.update_combat(1.0 / 60, 0, true, 0, 1, 0, 0, true) + check(absf(a.player.current_animation_position - .9) < .001, "contact frame at 0.90 s") + a.update_combat(1.0 / 60, 0, true, .65, 1, 0, 0, true) + check(a.current_clip == "attack_b", "alternating braced shot") + a.update_combat(1.0 / 60, 0, true, .65, 2, 0, 0, true) + check(a.current_clip == "attack_a", "third shot free again") + a.update_combat(1.0 / 60, 0, true, .65, 3, 0, 0, true) + check(a.current_clip == "ability", "fourth hit is the armor-piercing shot") + a.update_combat(1.0 / 60, 0, false, 0, 1, 0, 0, false) + check(a.dead and a.current_clip == "death", "death clip") + a.free() + b.free() + var f := FileAccess.open("res://docs/phase19-rig-verification.json", FileAccess.WRITE) + f.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + f.close() + print("RIG_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_glass.gd.uid b/tools/verify_glass.gd.uid new file mode 100644 index 0000000..54eb975 --- /dev/null +++ b/tools/verify_glass.gd.uid @@ -0,0 +1 @@ +uid://datgcrefc5eu6 diff --git a/tools/verify_glass.tscn b/tools/verify_glass.tscn new file mode 100644 index 0000000..b423f93 --- /dev/null +++ b/tools/verify_glass.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8glassverify"] + +[ext_resource type="Script" path="res://tools/verify_glass.gd" id="1"] + +[node name="VerifyGlass" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_material_sides.gd b/tools/verify_material_sides.gd new file mode 100644 index 0000000..17daa08 --- /dev/null +++ b/tools/verify_material_sides.gd @@ -0,0 +1,82 @@ +extends Node +## Render actual presentation materials from both sides; headless cannot prove visibility. +var checks: int = 0 +var failures: Array[String] = [] + +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("MATERIAL_FAIL: ", label) + +func _ready() -> void: + call_deferred("run") + +func run() -> void: + if DisplayServer.get_name() == "headless": + printerr("This material test requires a rendering display.") + await Soundscape.quit_game(1) + return + Soundscape.enabled = false + var view := SubViewport.new() + view.size = Vector2i(512, 256) + view.own_world_3d = true + view.render_target_update_mode = SubViewport.UPDATE_ALWAYS + add_child(view) + var world := WorldEnvironment.new() + world.environment = Environment.new() + world.environment.background_mode = Environment.BG_COLOR + world.environment.background_color = Color(.01, .01, .01) + world.environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR + world.environment.ambient_light_color = Color.WHITE + world.environment.ambient_light_energy = 1.0 + world.environment.reflected_light_source = Environment.REFLECTION_SOURCE_DISABLED + view.add_child(world) + var camera := Camera3D.new() + camera.projection = Camera3D.PROJECTION_ORTHOGONAL + camera.size = 2.4 + camera.position = Vector3(0, 0, 3) + view.add_child(camera) + var front := MeshInstance3D.new() + front.mesh = QuadMesh.new() + front.position.x = -.6 + view.add_child(front) + var back := MeshInstance3D.new() + back.mesh = front.mesh + back.position.x = .6 + back.rotation.y = PI + view.add_child(back) + var source: Node3D = load("res://assets/characters/quellgeflecht.glb").instantiate() + var surfaces: Dictionary = {} + for node: Node in source.find_children("*", "MeshInstance3D", true, false): + for index: int in range(node.mesh.get_surface_count()): + var material: Material = node.get_active_material(index) + if material.resource_name in ["QG_Leaf", "QG_Moss", "QG_Petal"]: + surfaces[material.resource_name] = material + check(surfaces.size() == 3, "all three imported foliage materials present") + var measurements: Dictionary = {} + for key: String in surfaces: + var original: StandardMaterial3D = surfaces[key] + check(original.cull_mode == BaseMaterial3D.CULL_DISABLED, key + " authored double-sided") + var material: Material = AssetLibrary.presentation_material(original) + front.material_override = material + back.material_override = material + for frame in range(5): + await get_tree().process_frame + await RenderingServer.frame_post_draw + var pixels := view.get_texture().get_image() + var front_pixel := camera.unproject_position(front.position) + var back_pixel := camera.unproject_position(back.position) + var front_light := pixels.get_pixelv(Vector2i(front_pixel)).get_luminance() + var back_light := pixels.get_pixelv(Vector2i(back_pixel)).get_luminance() + check(front_light > .15, key + " front is visible") + check(back_light > .15, key + " reverse side is visible") + check(absf(front_light - back_light) < .08, key + " sides have consistent ambient lighting") + measurements[key] = {"front_luminance": front_light, "back_luminance": back_light} + pixels.save_png("res://docs/screenshots/phase17/" + key.to_lower() + "-sides.png") + source.free() + var report := FileAccess.open("res://docs/phase17-material-verification.json", FileAccess.WRITE) + report.store_string(JSON.stringify({"checks": checks, "failures": failures, "renderer": RenderingServer.get_current_rendering_method(), "materials": measurements}, "\t")) + report.close() + print("MATERIAL_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_material_sides.gd.uid b/tools/verify_material_sides.gd.uid new file mode 100644 index 0000000..756b76e --- /dev/null +++ b/tools/verify_material_sides.gd.uid @@ -0,0 +1 @@ +uid://dlrtqsrwjgd27 diff --git a/tools/verify_material_sides.tscn b/tools/verify_material_sides.tscn new file mode 100644 index 0000000..90cfc80 --- /dev/null +++ b/tools/verify_material_sides.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/verify_material_sides.gd" id="1"] + +[node name="MaterialSideVerification" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_menu.gd b/tools/verify_menu.gd new file mode 100644 index 0000000..784fe4a --- /dev/null +++ b/tools/verify_menu.gd @@ -0,0 +1,239 @@ +extends Node +## Phase 20A acceptance: title menu, Bund selection, options, start/return/restart, input +## shielding, stage isolation, reduced motion and layout at 1280×720 / 1920×1080. +## Run: godot --path . --resolution 1920x1080 res://tools/verify_menu.tscn +var main: Node3D +var menu: MainMenu +var checks: int = 0 +var failures: Array[String] = [] + +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("MENU_FAIL: ", label) + +func _ready() -> void: + call_deferred("run") + +func frames(count: int = 3) -> void: + for i: int in range(count): + await get_tree().process_frame + +func click(control: Control) -> void: + # Like a player, scroll the setup panel until the control is in view. + var parent: Node = control.get_parent() + while parent != null and not parent is ScrollContainer: + parent = parent.get_parent() + if parent is ScrollContainer: + (parent as ScrollContainer).ensure_control_visible(control) + await frames(2) + var at: Vector2 = control.get_global_rect().get_center() + var motion := InputEventMouseMotion.new() + motion.position = at + get_viewport().push_input(motion, true) + await get_tree().process_frame + for pressed: bool in [true, false]: + var event := InputEventMouseButton.new() + event.button_index = MOUSE_BUTTON_LEFT + event.position = at + event.pressed = pressed + get_viewport().push_input(event, true) + await get_tree().process_frame + +func key(code: Key) -> void: + for pressed: bool in [true, false]: + var event := InputEventKey.new() + event.keycode = code + event.physical_keycode = code + event.pressed = pressed + get_viewport().push_input(event) + await get_tree().process_frame + +func settle() -> void: + while menu.is_transitioning() or menu.stage.is_moving(): + await get_tree().process_frame + await frames(2) + +func inside(control: Control, label: String) -> void: + var view := Rect2(Vector2.ZERO, get_viewport().get_visible_rect().size) + check(control.is_visible_in_tree() and view.encloses(control.get_global_rect()), label + " inside the window") + +func run() -> void: + Soundscape.enabled = false + WaveManager.set_physics_process(false) + var stored_path: String = Preferences.storage_path + var stored_reduced: bool = Preferences.reduced_motion + Preferences.storage_path = "user://phase20-menu-preferences.cfg" + Preferences.reduced_motion = false + GameState.factions = ["wurzelbund", "glutpakt"] + GameState.timed_build = false + GameState.ai_level = GameState.AI_LEARNING + var started: int = Time.get_ticks_msec() + main = load("res://scenes/main.tscn").instantiate() + add_child(main) + menu = main.hud.main_menu + var loaded: int = Time.get_ticks_msec() - started + await frames(4) + # ---- title and identity + check(GameState.phase == GameState.Phase.MENU and menu.visible, "Menu shows at start") + check(menu._title_screen.visible and not menu._setup_screen.visible, "Title screen first") + check(get_viewport().gui_get_focus_owner() == menu.new_game_button, "Keyboard focus starts on Neue Partie") + check(menu.theme == SaumwachtTheme.shared() and main.hud.settings_panel.theme == menu.theme, "Menu and options share one theme") + for variation: String in ["TitleLabel", "PrimaryButton", "ChoiceButton", "FactionCard", "MenuPanel", "QuietButton"]: + check(menu.theme.get_type_variation_base(variation) != StringName(), "Theme variation " + variation) + check(menu.new_game_button.theme_type_variation == "PrimaryButton" and menu._options_button.theme_type_variation == "Button", "Title entry outranks secondary entries") + for path: String in ["res://assets/ui/emblems/saumwacht.svg", "res://assets/ui/emblems/glutpakt.svg", "res://assets/ui/emblems/wurzelbund.svg"]: + check(load(path) is Texture2D, "Emblem " + path.get_file()) + # ---- stage isolation + check(menu.stage_view.own_world_3d and menu.stage.get_world_3d() != main.get_world_3d(), "Stage renders in its own World3D") + check(get_tree().root.disable_3d and menu.stage_view.render_target_update_mode == SubViewport.UPDATE_ALWAYS, "Menu renders only the stage") + check(main.battle.units.is_empty(), "No battle units exist in the menu") + var t0: int = Time.get_ticks_msec() + while not (menu.stage.is_ready("glutpakt") and menu.stage.is_ready("wurzelbund")) and Time.get_ticks_msec() - t0 < 15000: + await get_tree().process_frame + var ready_ms: int = Time.get_ticks_msec() - started + check(menu.stage.is_ready("glutpakt") and menu.stage.is_ready("wurzelbund"), "Both formations load") + var stage_units: int = 0 + for node: Node in menu.stage.find_children("*", "", true, false): + if node is CombatUnit: + stage_units += 1 + check(stage_units == 0, "Stage holds models, never combat units") + var skeletal: int = 0 + for faction: String in menu.stage.figures: + for figure: Node3D in menu.stage.figures[faction]: + if figure.has_method("update_combat"): + skeletal += 1 + check(skeletal >= 5, "Stage shows the real skeletal game models") + # ---- setup screen by mouse + await click(menu.new_game_button) + check(menu.screen == MainMenu.Screen.SETUP and menu.is_transitioning(), "Neue Partie opens the setup with a guarded fade") + await settle() + check(menu._setup_screen.visible and not menu._title_screen.visible, "Setup replaces the title") + check(menu.faction_choice.cards[1].has_focus(), "Focus lands on the selected Bund") + var wurzel := menu.faction_choice.cards[1] + var glut := menu.faction_choice.cards[0] + check(menu.faction_choice._badges[1].visible and not menu.faction_choice._badges[0].visible and menu.faction_choice._hints[0].visible, "Selection has a text badge, not only colour") + await click(glut) + check(GameState.factions[0] == "glutpakt" and main.hud._shop_buttons.has("g01"), "Clicking Glutpakt selects it and rebuilds the shop") + check(menu.stage.current_shot() == "glutpakt", "Shared preview follows the selection") + check(menu._setup_caption.text.contains("Glasballiste") and menu._style_heading.text.contains("GLUTPAKT"), "Caption and play style describe the selected Bund") + # ---- keyboard selection + glut.grab_focus() + await key(KEY_RIGHT) + check(wurzel.has_focus(), "Arrow key moves between Bund cards") + await key(KEY_ENTER) + check(GameState.factions[0] == "wurzelbund", "Enter selects the focused Bund") + await click(glut) + # ---- all previous match options + await click(menu.mode_choice.get_button(1)) + check(GameState.match_mode == GameState.MODE_SHORT and DataCatalog.wave_count() == 8 and menu.length_summary.text.begins_with("Acht"), "Short match selectable") + await click(menu.mode_choice.get_button(0)) + check(GameState.match_mode == GameState.MODE_EXPEDITION and "Zwanzig" in main.hud._overlay_title.text, "Expedition selectable") + check(not menu._advanced.visible, "Further settings start collapsed") + await click(menu._advanced_button) + await frames(3) + check(menu._advanced.visible, "Further settings open") + await click(menu.rival_choice.get_button(0)) + check(GameState.factions[1] == "glutpakt", "Rival Bund selectable") + await click(menu.ai_choice.get_button(1)) + check(GameState.ai_level == GameState.AI_STANDARD, "AI level selectable") + await click(menu.ai_choice.get_button(0)) + await click(menu.timed_toggle) + check(GameState.timed_build and menu._timed_hint.text.contains("45"), "Timed build selectable") + await click(menu.timed_toggle) + check(not GameState.timed_build, "Timed build can be switched off again") + await click(menu._advanced_button) + check(menu._advanced_summary.text.contains("Glutpakt") and menu._advanced_summary.text.contains("Lernmodus"), "Collapsed summary names every hidden option") + # ---- Esc back and forth + await key(KEY_ESCAPE) + check(menu.screen == MainMenu.Screen.TITLE, "Esc returns to the title") + await settle() + await click(menu.new_game_button) + await settle() + # ---- layout at both target sizes + for size: Vector2i in [Vector2i(1280, 720), Vector2i(1920, 1080)]: + get_window().size = size + await frames(8) + check(menu.stage_view.size == get_tree().root.size, "Stage follows window size %dx%d" % [size.x, size.y]) + inside(menu.start_button, "Start button %dx%d" % [size.x, size.y]) + inside(menu.faction_choice.cards[0], "Glutpakt card %dx%d" % [size.x, size.y]) + inside(menu.faction_choice.cards[1], "Wurzelbund card %dx%d" % [size.x, size.y]) + check(menu._setup_screen.get_node("SetupPanel").get_global_rect().encloses(menu.start_button.get_global_rect()), "Start button inside the setup panel %dx%d" % [size.x, size.y]) + # ---- start: the click that starts, and a click right after, never reach the board + var clicks_before: int = EconomyManager.get_team(0).roster.size() + await click(menu.start_button) + check(GameState.phase == GameState.Phase.BUILD and GameState.factions == ["glutpakt", "glutpakt"], "Partie beginnen starts the chosen setup") + check(menu.is_transitioning() or not menu.visible, "Menu leaves behind an input shield") + var cell: Vector2 = main.camera.unproject_position(Vector3(-14, 0, 3)) + for pressed: bool in [true, false]: + var event := InputEventMouseButton.new() + event.button_index = MOUSE_BUTTON_LEFT + event.position = cell + event.pressed = pressed + get_viewport().push_input(event, true) + await key(KEY_1) + check(EconomyManager.get_team(0).roster.size() == clicks_before and main.selected_uid < 0 and main.build_type.is_empty(), "No click or game key reaches the board during the fade") + main._clear_selection() + await get_tree().create_timer(.45).timeout + check(not menu.visible and not get_tree().root.disable_3d, "Menu hides and the arena renders again") + check(menu.stage_view.render_target_update_mode == SubViewport.UPDATE_DISABLED and menu.stage.process_mode == Node.PROCESS_MODE_DISABLED, "Stage stops rendering and animating during play") + var expected: int = EconomyManager.get_team(0).roster.size() + EconomyManager.get_team(1).roster.size() + var staged: bool = true + for faction: String in menu.stage.figures: + for figure: Node3D in menu.stage.figures[faction]: + staged = staged and menu.stage.is_ancestor_of(figure) + check(main.battle.units.size() == expected and EconomyManager.get_team(0).roster.is_empty() and staged, "Only roster units enter the match; stage figures stay in the stage") + check(EconomyManager.get_team(0).gold == 220 and GameState.wave == 1, "Match starts with ordinary resources") + await click(main.hud._starter_button) + check(EconomyManager.get_team(0).roster.size() == 3, "Board input works after the fade") + # ---- return to the menu and start again + main.hud.main_menu.pending_screen = MainMenu.Screen.SETUP + main.hud.menu_requested.emit() + await frames(4) + check(GameState.phase == GameState.Phase.MENU and menu.visible and menu.screen == MainMenu.Screen.SETUP, "Neue Partie in the options returns to the Bund selection") + check(get_tree().root.disable_3d and EconomyManager.get_team(0).roster.is_empty(), "Returning clears the match and resumes the stage") + await click(menu.faction_choice.cards[1]) + await click(menu.start_button) + check(GameState.phase == GameState.Phase.BUILD and GameState.factions[0] == "wurzelbund" and EconomyManager.get_team(0).gold == 220, "Second start uses the new choice") + await get_tree().create_timer(.45).timeout + # ---- result screen and replay + GameState.outcome = 1 + GameState.core_hp = [0, 1500] + GameState.set_phase(GameState.Phase.GAME_OVER) + await frames(4) + check(menu.visible and menu._result_panel.visible and menu.result_title.text == "NIEDERLAGE AM SAUM", "Result screen names the outcome in words") + check(menu.new_game_button.text == "NOCHMAL SPIELEN" and menu._change_button.visible, "Result offers replay and setup") + await click(menu.new_game_button) + check(GameState.phase == GameState.Phase.BUILD and GameState.wave == 1 and GameState.core_hp == [3000, 3000], "Replay starts a fresh match") + await get_tree().create_timer(.45).timeout + main.hud.menu_requested.emit() + await frames(4) + # ---- options from the menu, reduced motion, settings round trip + main.hud.toggle_settings() + check(main.hud.settings_panel.visible and main.hud._reduced_check != null, "Options open from the menu with Bewegung reduzieren") + main.hud._reduced_check.button_pressed = true + await frames(2) + check(Preferences.reduced_motion and menu.reduced_motion and menu.stage.reduced_motion, "Reduced motion reaches menu and stage") + var particles_hidden: bool = true + for particles: GPUParticles3D in menu.stage._particles: + particles_hidden = particles_hidden and not particles.visible + check(particles_hidden, "Reduced motion hides menu particles") + main.hud.toggle_settings() + await click(menu.new_game_button) + check(not menu.is_transitioning() and not menu.stage.is_moving(), "Reduced motion switches screens and shots instantly") + Preferences.reduced_motion = false + Preferences.read_settings() + check(Preferences.reduced_motion, "Reduced motion survives a settings reload") + # ---- report + DirAccess.remove_absolute(Preferences.storage_path) + Preferences.storage_path = stored_path + Preferences.reduced_motion = stored_reduced + Preferences.apply() + var report := {"checks": checks, "failures": failures, "menu_instantiate_ms": loaded, "formations_ready_ms": ready_ms, + "renderer": RenderingServer.get_current_rendering_method(), "engine": Engine.get_version_info().string} + var file := FileAccess.open("res://docs/phase20-menu-verification.json", FileAccess.WRITE) + file.store_string(JSON.stringify(report, "\t")) + file.close() + print("MENU_VERIFY_%s: %d checks; %d failures" % ["PASS" if failures.is_empty() else "FAIL", checks, failures.size()]) + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_menu.gd.uid b/tools/verify_menu.gd.uid new file mode 100644 index 0000000..93b439d --- /dev/null +++ b/tools/verify_menu.gd.uid @@ -0,0 +1 @@ +uid://0ynq8yfwqf5b diff --git a/tools/verify_menu.tscn b/tools/verify_menu.tscn new file mode 100644 index 0000000..5bff53f --- /dev/null +++ b/tools/verify_menu.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/verify_menu.gd" id="1"] + +[node name="VerifyMenu" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_phase3_imports.gd b/tools/verify_phase3_imports.gd new file mode 100644 index 0000000..9972056 --- /dev/null +++ b/tools/verify_phase3_imports.gd @@ -0,0 +1,140 @@ +extends SceneTree +## Read-only verification after Godot has imported the Phase 3 assets. +## Run: godot --headless --path . --script res://tools/verify_phase3_imports.gd + +const MANIFEST_PATH: String = "res://assets/phase3_manifest.json" +const EXPECTED_ASSET_COUNT: int = 66 +const ALPHA_TOLERANCE: float = 0.02 + +var _errors: Array[String] = [] +var _checked: int = 0 +var _loaded: int = 0 + + +func _initialize() -> void: + call_deferred("_run") + + +func _run() -> void: + if not FileAccess.file_exists(MANIFEST_PATH): + _fail("manifest", "File is missing: " + MANIFEST_PATH) + _finish() + return + var file: FileAccess = FileAccess.open(MANIFEST_PATH, FileAccess.READ) + if file == null: + _fail("manifest", "Cannot open file: %s" % FileAccess.get_open_error()) + _finish() + return + var parser: JSON = JSON.new() + var parse_error: Error = parser.parse(file.get_as_text()) + file.close() + if parse_error != OK: + _fail("manifest", "JSON line %d: %s" % [parser.get_error_line(), parser.get_error_message()]) + _finish() + return + var parsed: Variant = parser.data + if not parsed is Dictionary: + _fail("manifest", "Root must be an object.") + _finish() + return + var manifest: Dictionary = parsed + if manifest.get("phase") != 3: + _fail("manifest", "Expected phase 3.") + var entries_value: Variant = manifest.get("assets") + if not entries_value is Array: + _fail("manifest", "assets must be an array.") + _finish() + return + var entries: Array = entries_value + if entries.size() != EXPECTED_ASSET_COUNT: + _fail("manifest", "Expected %d assets, found %d." % [EXPECTED_ASSET_COUNT, entries.size()]) + var seen_ids: Dictionary = {} + for index: int in range(entries.size()): + _checked += 1 + var entry_value: Variant = entries[index] + if not entry_value is Dictionary: + _fail("entry_%d" % index, "Asset entry must be an object.") + continue + var entry: Dictionary = entry_value + var asset_id: String = str(entry.get("id", "")) + if asset_id.is_empty(): + _fail("entry_%d" % index, "Asset ID is missing.") + continue + if seen_ids.has(asset_id): + _fail(asset_id, "Duplicate asset ID.") + seen_ids[asset_id] = true + _verify_asset(asset_id, entry) + _finish() + + +func _verify_asset(asset_id: String, entry: Dictionary) -> void: + for required_key: String in ["kind", "resource_path", "width", "height", "import_size_limit", "requires_alpha"]: + if not entry.has(required_key): + _fail(asset_id, "Missing manifest field: " + required_key) + return + var resource_path: String = str(entry["resource_path"]) + var native_size: Vector2i = Vector2i(int(entry["width"]), int(entry["height"])) + var size_limit: int = int(entry["import_size_limit"]) + if native_size.x <= 0 or native_size.y <= 0 or size_limit < 0: + _fail(asset_id, "Invalid native size or import limit.") + return + if not resource_path.begins_with("res://") or not ResourceLoader.exists(resource_path): + _fail(asset_id, "Resource is missing: " + resource_path) + return + var texture: Texture2D = ResourceLoader.load(resource_path) as Texture2D + if texture == null: + _fail(asset_id, "Resource did not load as Texture2D: " + resource_path) + return + _loaded += 1 + var expected_size: Vector2i = _expected_size(native_size, size_limit) + var texture_size: Vector2i = Vector2i(texture.get_width(), texture.get_height()) + if texture_size != expected_size: + _fail(asset_id, "Texture size %s; expected %s (native %s, limit %d)." % [texture_size, expected_size, native_size, size_limit]) + var texture_image: Image = texture.get_image() + if texture_image == null or texture_image.is_empty(): + _fail(asset_id, "Texture2D.get_image() returned no pixel data.") + return + if texture_image.get_size() != expected_size: + _fail(asset_id, "Image size %s; expected %s." % [texture_image.get_size(), expected_size]) + if not bool(entry["requires_alpha"]): + return + if texture_image.is_compressed(): + # Decompress the returned in-memory Image only; never save or reimport it. + var decompress_error: Error = texture_image.decompress() + if decompress_error != OK: + _fail(asset_id, "Cannot inspect compressed image alpha: %s" % decompress_error) + return + if texture_image.detect_alpha() == Image.ALPHA_NONE: + _fail(asset_id, "Image has no effective alpha transparency.") + var corner_alpha: float = texture_image.get_pixel(0, 0).a + if corner_alpha > ALPHA_TOLERANCE: + _fail(asset_id, "Corner alpha %.4f; expected at most %.4f." % [corner_alpha, ALPHA_TOLERANCE]) + if str(entry["kind"]) == "ui_frame": + var center_x: int = floori(float(texture_image.get_width()) * 0.5) + var center_y: int = floori(float(texture_image.get_height()) * 0.5) + var center_alpha: float = texture_image.get_pixel(center_x, center_y).a + if center_alpha > ALPHA_TOLERANCE: + _fail(asset_id, "Panel center alpha %.4f; expected at most %.4f." % [center_alpha, ALPHA_TOLERANCE]) + + +func _expected_size(native_size: Vector2i, size_limit: int) -> Vector2i: + if size_limit == 0: + return native_size + var longest_side: int = maxi(native_size.x, native_size.y) + var scale_factor: float = minf(1.0, float(size_limit) / float(longest_side)) + return Vector2i( + maxi(1, roundi(float(native_size.x) * scale_factor)), + maxi(1, roundi(float(native_size.y) * scale_factor)) + ) + + +func _fail(asset_id: String, message: String) -> void: + _errors.append("[%s] %s" % [asset_id, message]) + + +func _finish() -> void: + for message: String in _errors: + printerr("FAIL: " + message) + var result_label: String = "PASS" if _errors.is_empty() else "FAIL" + print("%s: Phase 3 imports: %d entries checked, %d/%d textures loaded, %d errors." % [result_label, _checked, _loaded, EXPECTED_ASSET_COUNT, _errors.size()]) + quit(0 if _errors.is_empty() else 1) diff --git a/tools/verify_phase3_imports.gd.uid b/tools/verify_phase3_imports.gd.uid new file mode 100644 index 0000000..f4ec6dc --- /dev/null +++ b/tools/verify_phase3_imports.gd.uid @@ -0,0 +1 @@ +uid://crx0pmqwfu2at diff --git a/tools/verify_phase4_gallery.gd b/tools/verify_phase4_gallery.gd new file mode 100644 index 0000000..ddb7959 --- /dev/null +++ b/tools/verify_phase4_gallery.gd @@ -0,0 +1,35 @@ +extends SceneTree +## Actual UI smoke check and fresh workshop screenshot. Requires a display. + +func _initialize() -> void: + call_deferred("_run") + +func _run() -> void: + var gallery: Control = load("res://tools/model_gallery.tscn").instantiate() + root.add_child(gallery) + await process_frame + assert(gallery._asset_select.item_count == 59) + assert(gallery._icon.texture != null) + for index: int in range(gallery._faction_select.item_count): + if gallery._faction_select.get_item_metadata(index) == "nebelchor": + gallery._faction_select.select(index) + gallery._faction_select.item_selected.emit(index) + assert(gallery._asset_select.item_count == 10) + gallery._asset_select.select(7) + gallery._asset_select.item_selected.emit(7) + assert(gallery._title.text == "Hohlgeläut") + assert(gallery._icon.texture != null) + var turntable: Node3D = gallery._view["turntable"] + assert(turntable.get_child_count() == 1) + gallery._auto_rotate.button_pressed = true + await create_timer(0.25).timeout + assert(turntable.rotation.y > 0.0) + gallery._auto_rotate.button_pressed = false + gallery._reset_view() + assert(turntable.rotation == Vector3.ZERO) + await process_frame + await RenderingServer.frame_post_draw + var result: Error = root.get_texture().get_image().save_png("res://docs/screenshots/phase4/models-workshop.png") + assert(result == OK) + print("GALLERY_PASS: 59 entries, faction filter, N08 reference, rotation, reset and screenshot") + quit(0) diff --git a/tools/verify_phase4_gallery.gd.uid b/tools/verify_phase4_gallery.gd.uid new file mode 100644 index 0000000..377aa6d --- /dev/null +++ b/tools/verify_phase4_gallery.gd.uid @@ -0,0 +1 @@ +uid://1em8yiphpboo diff --git a/tools/verify_phase4_glb.py b/tools/verify_phase4_glb.py new file mode 100644 index 0000000..682d56c --- /dev/null +++ b/tools/verify_phase4_glb.py @@ -0,0 +1,306 @@ +#!/usr/bin/env python3 +"""Read-only structural and geometry audit of the Phase 4 GLB package. + +Uses only Python's standard library. Nothing is imported into Blender or Godot, +and neither assets nor reports are modified. --json emits machine-readable QA. +Open meshes are warnings, because horns and cutout surfaces may be intentional. +Closed meshes with negative signed volume are errors: their winding faces inward. +""" + +import argparse +from collections import Counter +import hashlib +import json +import math +from pathlib import Path +import re +import struct +import sys + + +PROJECT = Path(__file__).resolve().parents[1] +COMPONENTS = {5120: ("b", 1), 5121: ("B", 1), 5122: ("h", 2), + 5123: ("H", 2), 5125: ("I", 4), 5126: ("f", 4)} +WIDTHS = {"SCALAR": 1, "VEC2": 2, "VEC3": 3, "VEC4": 4, + "MAT2": 4, "MAT3": 9, "MAT4": 16} + + +def require(condition, message): + if not condition: + raise ValueError(message) + + +def finite(values): + return all(isinstance(value, (int, float)) and math.isfinite(value) for value in values) + + +def sub(a, b): + return tuple(x - y for x, y in zip(a, b)) + + +def cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def dot(a, b): + return sum(x * y for x, y in zip(a, b)) + + +class GLB: + def __init__(self, path): + self.raw = path.read_bytes() + require(len(self.raw) >= 20, "Truncated GLB header") + magic, version, length = struct.unpack_from("<4sII", self.raw) + require((magic, version, length) == (b"glTF", 2, len(self.raw)), "Invalid GLB header") + chunks, offset = [], 12 + while offset < length: + require(offset + 8 <= length, "Truncated GLB chunk header") + size, kind = struct.unpack_from(" 0, "Empty accessor") + views = self.doc.get("bufferViews", []) + view_index = accessor.get("bufferView", -1) + require(isinstance(view_index, int) and 0 <= view_index < len(views), "Invalid bufferView") + view = views[view_index] + require(view.get("buffer") == 0, "Invalid embedded buffer reference") + fmt, size = COMPONENTS[component] + width = WIDTHS[accessor["type"]] + item_size = width * size + # Matrices are not used in these static models; byte/short matrix padding + # requires a different decoder, and must never be silently misinterpreted. + require(not accessor["type"].startswith("MAT") or size == 4, "Packed matrix accessor") + stride = view.get("byteStride", item_size) + require(stride >= item_size and stride % size == 0, "Invalid accessor stride") + start = view.get("byteOffset", 0) + local = accessor.get("byteOffset", 0) + require(start >= 0 and local >= 0 and view["byteLength"] >= 0, "Negative buffer offset") + require(start + view["byteLength"] <= self.buffer_length, "bufferView exceeds BIN") + end = local + (accessor["count"] - 1) * stride + item_size + require(end <= view["byteLength"], "Accessor exceeds bufferView") + unpack = struct.Struct("<" + fmt * width).unpack_from + values = [unpack(self.binary, start + local + i * stride) for i in range(accessor["count"])] + self.cache[index] = values + return values + + +def topology(vertices, triangles): + """Weld equal-position flat-shading vertices to assess the actual surface.""" + welded = {} + ids = [] + for point in vertices: + key = tuple(round(coordinate, 6) for coordinate in point) + if key not in welded: + welded[key] = len(welded) + ids.append(welded[key]) + edges, orientations = Counter(), Counter() + volume_terms = [] + degenerate = 0 + for a, b, c in triangles: + points = (vertices[a], vertices[b], vertices[c]) + area = cross(sub(points[1], points[0]), sub(points[2], points[0])) + if len({ids[a], ids[b], ids[c]}) < 3 or dot(area, area) <= 1e-22: + degenerate += 1 + continue + volume_terms.append(dot(points[0], cross(points[1], points[2])) / 6) + for start, end in ((ids[a], ids[b]), (ids[b], ids[c]), (ids[c], ids[a])): + edge = tuple(sorted((start, end))) + edges[edge] += 1 + orientations[edge] += 1 if start < end else -1 + boundary = sum(count == 1 for count in edges.values()) + nonmanifold = sum(count > 2 for count in edges.values()) + inconsistent = sum(edges[edge] == 2 and direction != 0 for edge, direction in orientations.items()) + closed = bool(edges) and boundary == nonmanifold == inconsistent == 0 + return {"closed": closed, "boundary_edges": boundary, "nonmanifold_edges": nonmanifold, + "inconsistent_edges": inconsistent, "degenerate_triangles": degenerate, + "signed_volume": math.fsum(volume_terms)} + + +def audit_asset(project, record): + identifier = record["id"] + path = project / "assets" / "models" / record["file"] + glb = GLB(path) + doc = glb.doc + result = {"id": identifier, "file": record["file"], "errors": [], "warnings": [], + "triangles": 0, "mesh_parts": 0, "primitives": 0, "vertices": 0, + "closed_meshes": 0, "open_meshes": [], "inward_meshes": [], + "degenerate_triangles": 0} + require(hashlib.sha256(glb.raw).hexdigest() == record["sha256"], "Manifest SHA-256 mismatch") + require(len(doc.get("scenes", [])) == 1 and doc.get("scene", 0) == 0, "Expected exactly one default scene") + require(not doc.get("cameras"), "Unexpected camera") + require(not doc.get("extensions", {}).get("KHR_lights_punctual", {}).get("lights"), "Unexpected light") + require(not doc.get("animations") and not doc.get("skins"), "Unexpected animation or skin") + nodes, meshes, materials = doc.get("nodes", []), doc.get("meshes", []), doc.get("materials", []) + require(bool(nodes) and bool(meshes) and bool(materials), "Missing nodes, meshes or materials") + expected = set(record["parts"]) | {"Model_" + identifier, "Forward"} + names = [node.get("name", "") for node in nodes] + require(len(set(names)) == len(names), "Duplicate node names") + require(set(names) == expected, "Node/part inventory differs from manifest") + for node in nodes: + name = node.get("name") + require(node.get("extras", {}).get("part_name") == name, "Unstable logical part name: " + str(name)) + require(not re.search(r"\.\d{3}$", name), "Blender numeric suffix: " + name) + require(not re.fullmatch(r"(?:Cube|Camera|Light|Lamp)(?:\.\d+)?", name), "Factory object: " + name) + require("camera" not in node and "KHR_lights_punctual" not in node.get("extensions", {}), + "Camera/light node: " + name) + for key, width in (("translation", 3), ("rotation", 4), ("scale", 3), ("matrix", 16)): + if key in node: + require(len(node[key]) == width and finite(node[key]), "Invalid node transform: " + name) + roots = doc["scenes"][0].get("nodes", []) + require(len(roots) == 1 and nodes[roots[0]].get("name") == "Model_" + identifier, "Unexpected model root") + visited = set() + + def visit(index): + require(isinstance(index, int) and 0 <= index < len(nodes), "Invalid scene node index") + require(index not in visited, "Node cycle or multiple parents") + visited.add(index) + for child in nodes[index].get("children", []): + visit(child) + + visit(roots[0]) + require(len(visited) == len(nodes), "Unreachable extra nodes") + mesh_indices = [node["mesh"] for node in nodes if "mesh" in node] + require(all(isinstance(index, int) and 0 <= index < len(meshes) for index in mesh_indices), "Invalid mesh reference") + require(sorted(mesh_indices) == list(range(len(meshes))), "Unused or shared unexpected mesh datablock") + result["mesh_parts"] = len(meshes) + for node in nodes: + if "mesh" not in node: + continue + mesh = meshes[node["mesh"]] + mesh_vertices, mesh_triangles = [], [] + require(bool(mesh.get("primitives")), "Mesh has no surfaces: " + node["name"]) + for primitive in mesh["primitives"]: + result["primitives"] += 1 + require(primitive.get("mode", 4) == 4, "Non-triangle primitive") + material = primitive.get("material", -1) + require(isinstance(material, int) and 0 <= material < len(materials), "Surface without valid material") + attributes = primitive.get("attributes", {}) + require("POSITION" in attributes and "NORMAL" in attributes, "Surface lacks positions or normals") + for attribute in ("POSITION", "NORMAL"): + accessor = doc["accessors"][attributes[attribute]] + require(accessor["type"] == "VEC3" and accessor["componentType"] == 5126, + "Expected float VEC3 " + attribute) + positions, normals = glb.accessor(attributes["POSITION"]), glb.accessor(attributes["NORMAL"]) + require(len(positions) == len(normals), "Position/normal count mismatch") + require(all(finite(point) for point in positions), "Non-finite vertex position") + require(all(finite(normal) and abs(dot(normal, normal) - 1) < 0.005 for normal in normals), + "Non-finite, zero or non-unit normal") + if "indices" in primitive: + accessor = doc["accessors"][primitive["indices"]] + require(accessor["type"] == "SCALAR" and accessor["componentType"] in (5121, 5123, 5125), + "Invalid index accessor type") + indices = [value[0] for value in glb.accessor(primitive["indices"])] + else: + indices = list(range(len(positions))) + require(len(indices) % 3 == 0 and len(indices) > 0, "Invalid triangle index count") + require(all(0 <= index < len(positions) for index in indices), "Index outside POSITION array") + triangles = [tuple(indices[i:i + 3]) for i in range(0, len(indices), 3)] + for a, b, c in triangles: + face_normal = cross(sub(positions[b], positions[a]), sub(positions[c], positions[a])) + require(all(dot(face_normal, normals[index]) >= -1e-7 for index in (a, b, c)), + "Normals oppose face winding: " + node["name"]) + offset = len(mesh_vertices) + mesh_vertices.extend(positions) + mesh_triangles.extend(tuple(index + offset for index in triangle) for triangle in triangles) + result["triangles"] += len(triangles) + result["vertices"] += len(positions) + info = topology(mesh_vertices, mesh_triangles) + result["degenerate_triangles"] += info["degenerate_triangles"] + if info["closed"]: + result["closed_meshes"] += 1 + if info["signed_volume"] < -1e-10: + result["inward_meshes"].append(node["name"]) + result["errors"].append("Closed mesh has inward winding: " + node["name"]) + else: + result["open_meshes"].append({"part": node["name"], **info}) + result["warnings"].append("Open/nonmanifold mesh: " + node["name"]) + require(result["triangles"] == record["triangles"], "Triangle count differs from manifest") + require(result["mesh_parts"] == record["mesh_parts"], "Mesh part count differs from manifest") + require(result["triangles"] <= int(record.get("triangle_budget", 3000 if record["role"] in ("core", "lane") else 1800)), "Triangle budget exceeded") + if result["degenerate_triangles"]: + result["warnings"].append(str(result["degenerate_triangles"]) + " degenerate triangles") + result["part_names"] = sorted(record["parts"]) + return result + + +def audit(project): + manifest = json.loads((project / "assets" / "phase4_manifest.json").read_text()) + records = manifest["assets"] + result = {"asset_count": len(records), "errors": [], "assets": [], "upgrade_pairs": []} + if manifest.get("asset_count") != len(records) or len(records) != 59: + result["errors"].append("Expected manifest inventory of exactly 59 assets") + if len({record["id"] for record in records}) != len(records): + result["errors"].append("Duplicate asset IDs") + actual_files = {path.name for path in (project / "assets" / "models").glob("*.glb")} + if actual_files != {record["file"] for record in records}: + result["errors"].append("GLB directory inventory differs from manifest") + for record in records: + try: + asset = audit_asset(project, record) + except (ValueError, KeyError, IndexError, TypeError, OSError, struct.error) as error: + asset = {"id": record["id"], "errors": [str(error)], "warnings": []} + result["assets"].append(asset) + by_id = {asset["id"]: asset for asset in result["assets"]} + for faction in "gmnw": + for base_number in range(1, 10, 2): + base, upgrade = faction + f"{base_number:02}", faction + f"{base_number + 1:02}" + a, b = by_id.get(base, {}), by_id.get(upgrade, {}) + different = ("part_names" in a and "part_names" in b and + (a["part_names"] != b["part_names"] or a["triangles"] != b["triangles"])) + result["upgrade_pairs"].append({"base": base, "upgrade": upgrade, + "structurally_distinct": different}) + if not different: + result["errors"].append(base + "/" + upgrade + ": no proven geometry/part difference") + result["passed"] = not result["errors"] and all(not asset["errors"] for asset in result["assets"]) + result["warning_count"] = sum(len(asset["warnings"]) for asset in result["assets"]) + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--project", type=Path, default=PROJECT) + parser.add_argument("--json", action="store_true", help="Print the full audit as JSON") + args = parser.parse_args() + result = audit(args.project.resolve()) + if args.json: + print(json.dumps(result, ensure_ascii=False, indent=2)) + else: + passed = sum(not asset["errors"] for asset in result["assets"]) + print(f"Phase 4 GLB audit: {passed}/{result['asset_count']} assets passed") + print(f"Upgrade pairs: {sum(pair['structurally_distinct'] for pair in result['upgrade_pairs'])}/20 distinct") + print(f"Warnings: {result['warning_count']}") + for error in result["errors"]: + print("ERROR: " + error) + for asset in result["assets"]: + for error in asset["errors"]: + print("ERROR " + asset["id"] + ": " + error) + for warning in asset["warnings"]: + print("WARNING " + asset["id"] + ": " + warning) + return 0 if result["passed"] else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/verify_phase4_models.gd b/tools/verify_phase4_models.gd new file mode 100644 index 0000000..6f80539 --- /dev/null +++ b/tools/verify_phase4_models.gd @@ -0,0 +1,246 @@ +extends SceneTree +## Read-only inspection of Godot's imported GLB scenes, including real geometry. +## Run after import: godot --headless --path . --script res://tools/verify_phase4_models.gd + +const MANIFEST_PATH: String = "res://assets/phase4_manifest.json" +const EXPECTED_ASSET_COUNT: int = 59 +const TOLERANCE: float = 0.003 + +var _errors: Array[String] = [] +var _checked: int = 0 +var _passed: int = 0 + + +func _initialize() -> void: + call_deferred("_run") + + +func _run() -> void: + var file: FileAccess = FileAccess.open(MANIFEST_PATH, FileAccess.READ) + if file == null: + _fail("manifest", "Cannot open %s: %s" % [MANIFEST_PATH, FileAccess.get_open_error()]) + _finish() + return + var parser: JSON = JSON.new() + var parse_error: Error = parser.parse(file.get_as_text()) + file.close() + if parse_error != OK: + _fail("manifest", "JSON line %d: %s" % [parser.get_error_line(), parser.get_error_message()]) + _finish() + return + if not parser.data is Dictionary: + _fail("manifest", "Root must be an object.") + _finish() + return + var manifest: Dictionary = parser.data + if manifest.get("phase") != 4: + _fail("manifest", "Expected phase 4.") + if manifest.get("asset_count") != EXPECTED_ASSET_COUNT: + _fail("manifest", "asset_count must be %d." % EXPECTED_ASSET_COUNT) + var entries_value: Variant = manifest.get("assets") + if not entries_value is Array: + _fail("manifest", "assets must be an array.") + _finish() + return + var entries: Array = entries_value + if entries.size() != EXPECTED_ASSET_COUNT: + _fail("manifest", "Expected %d entries, found %d." % [EXPECTED_ASSET_COUNT, entries.size()]) + var seen_ids: Dictionary = {} + for index: int in range(entries.size()): + _checked += 1 + var errors_before: int = _errors.size() + if not entries[index] is Dictionary: + _fail("entry_%d" % index, "Entry must be an object.") + continue + var entry: Dictionary = entries[index] + var asset_id: String = str(entry.get("id", "")) + if asset_id.is_empty(): + _fail("entry_%d" % index, "Asset ID is missing.") + continue + if seen_ids.has(asset_id): + _fail(asset_id, "Duplicate asset ID.") + seen_ids[asset_id] = true + _verify_asset(asset_id, entry) + if _errors.size() == errors_before: + _passed += 1 + _finish() + + +func _verify_asset(asset_id: String, entry: Dictionary) -> void: + for required: String in ["role", "resource_path", "triangles", "mesh_parts", "bounds_godot", "parts"]: + if not entry.has(required): + _fail(asset_id, "Missing field: " + required) + return + if not entry["parts"] is Array or not entry["bounds_godot"] is Dictionary: + _fail(asset_id, "parts must be an array and bounds_godot must be an object.") + return + var bounds_record: Dictionary = entry["bounds_godot"] + var errors_before: int = _errors.size() + var expected_min: Vector3 = _read_vector(asset_id, bounds_record.get("min"), "bounds.min") + var expected_max: Vector3 = _read_vector(asset_id, bounds_record.get("max"), "bounds.max") + if _errors.size() != errors_before: + return + if not _positive_size(expected_max - expected_min): + _fail(asset_id, "Manifest bounds must have finite positive size on every axis.") + return + var resource_path: String = str(entry["resource_path"]) + if not resource_path.begins_with("res://") or not ResourceLoader.exists(resource_path): + _fail(asset_id, "Resource is missing: " + resource_path) + return + var packed: PackedScene = ResourceLoader.load(resource_path) as PackedScene + if packed == null: + _fail(asset_id, "Resource did not load as PackedScene: " + resource_path) + return + var instance: Node = packed.instantiate() + if instance == null: + _fail(asset_id, "PackedScene could not instantiate.") + return + root.add_child(instance) + _verify_instance(asset_id, entry, instance, expected_min, expected_max) + root.remove_child(instance) + instance.free() + + +func _verify_instance(asset_id: String, entry: Dictionary, instance: Node, + expected_min: Vector3, expected_max: Vector3) -> void: + var nodes: Array[Node] = [] + _collect_nodes(instance, nodes) + var names: Dictionary = {} + var meshes: Array[MeshInstance3D] = [] + for node: Node in nodes: + var logical_name: String = str(node.name) + if not names.has(logical_name): + names[logical_name] = [] + var named_nodes: Array = names[logical_name] + named_nodes.append(node) + if node is MeshInstance3D: + meshes.append(node as MeshInstance3D) + var expected_parts: Array = entry["parts"] + var seen_parts: Dictionary = {} + for part_value: Variant in expected_parts: + var part_name: String = str(part_value) + if part_name.is_empty() or seen_parts.has(part_name): + _fail(asset_id, "Empty or duplicate manifest part: " + part_name) + seen_parts[part_name] = true + if not names.has(part_name): + _fail(asset_id, "Missing logical part node: " + part_name) + elif (names[part_name] as Array).size() != 1: + _fail(asset_id, "Logical part node is ambiguous: " + part_name) + _check_origin_and_forward(asset_id, names) + if meshes.size() != int(entry["mesh_parts"]): + _fail(asset_id, "Mesh count %d; expected %d." % [meshes.size(), int(entry["mesh_parts"])]) + if meshes.is_empty(): + _fail(asset_id, "Scene contains no MeshInstance3D nodes.") + return + var aggregate: AABB = AABB() + var has_bounds: bool = false + var triangles: int = 0 + for mesh_node: MeshInstance3D in meshes: + var mesh: Mesh = mesh_node.mesh + if mesh == null: + _fail(asset_id, "%s has no mesh resource." % mesh_node.name) + continue + if mesh.get_surface_count() <= 0: + _fail(asset_id, "%s has no mesh surfaces." % mesh_node.name) + for surface: int in range(mesh.get_surface_count()): + var material: Material = mesh_node.get_active_material(surface) + if material == null or not is_instance_valid(material): + _fail(asset_id, "%s surface %d has no valid material." % [mesh_node.name, surface]) + var faces: PackedVector3Array = mesh.get_faces() + if faces.is_empty() or faces.size() % 3 != 0: + _fail(asset_id, "%s has invalid triangle face data." % mesh_node.name) + triangles += int(faces.size() / 3) + # Transform every local mesh box before merging; transforming the merged + # local bounds would give wrong results for rotated or translated parts. + var world_box: AABB = mesh_node.global_transform * mesh.get_aabb() + if not world_box.position.is_finite() or not world_box.size.is_finite(): + _fail(asset_id, "%s has non-finite world bounds." % mesh_node.name) + continue + aggregate = aggregate.merge(world_box) if has_bounds else world_box + has_bounds = true + if triangles != int(entry["triangles"]): + _fail(asset_id, "Triangle count %d; expected %d." % [triangles, int(entry["triangles"])]) + var role: String = str(entry["role"]) + var triangle_cap: int = int(entry.get("triangle_budget", 3000 if role in ["core", "lane"] else 1800)) + if triangles <= 0 or triangles > triangle_cap: + _fail(asset_id, "Triangle count %d is outside 1–%d." % [triangles, triangle_cap]) + if not has_bounds or not _positive_size(aggregate.size): + _fail(asset_id, "Imported aggregate bounds must have finite positive size.") + return + if not _near_vector(aggregate.position, expected_min) or not _near_vector(aggregate.end, expected_max): + _fail(asset_id, "Bounds %s…%s; expected %s…%s (tolerance %.3f m)." % [ + aggregate.position, aggregate.end, expected_min, expected_max, TOLERANCE]) + if role != "lane": + if absf(aggregate.position.y) > TOLERANCE: + _fail(asset_id, "Ground origin differs: minimum Y = %.6f m." % aggregate.position.y) + # Older hand-written manifests can omit the catalog's footprint field. + var default_footprint: float = 3.2 if role == "core" else (1.4 if role == "worker" else 1.85) + var footprint: float = float(entry.get("footprint", default_footprint)) + if not is_finite(footprint) or footprint <= 0.0: + _fail(asset_id, "Invalid footprint limit.") + elif maxf(aggregate.size.x, aggregate.size.z) > footprint + TOLERANCE: + _fail(asset_id, "XZ extent %.6f exceeds footprint %.3f m." % [maxf(aggregate.size.x, aggregate.size.z), footprint]) + + +func _check_origin_and_forward(asset_id: String, names: Dictionary) -> void: + var root_name: String = "Model_" + asset_id + for required: String in [root_name, "Forward"]: + if not names.has(required) or (names[required] as Array).size() != 1: + _fail(asset_id, "Expected one named node: " + required) + return + var model: Node3D = (names[root_name] as Array)[0] as Node3D + var forward: Node3D = (names["Forward"] as Array)[0] as Node3D + if model == null or forward == null: + _fail(asset_id, "Model root and Forward marker must be Node3D nodes.") + return + var transform: Transform3D = model.global_transform + if not _near_vector(transform.origin, Vector3.ZERO): + _fail(asset_id, "Model root is not at the world origin: %s." % transform.origin) + if not _near_vector(transform.basis.x, Vector3.RIGHT) or not _near_vector(transform.basis.y, Vector3.UP) or not _near_vector(transform.basis.z, Vector3.BACK): + _fail(asset_id, "Model root basis must have identity rotation and scale.") + if not _near_vector(forward.global_position, Vector3(0.0, 0.0, 0.75)): + _fail(asset_id, "Forward marker %s; expected Godot +Z at 0.75 m." % forward.global_position) + if not model.is_ancestor_of(forward): + _fail(asset_id, "Forward marker must be a child of the model root.") + + +func _collect_nodes(node: Node, result: Array[Node]) -> void: + result.append(node) + for child: Node in node.get_children(): + _collect_nodes(child, result) + + +func _read_vector(asset_id: String, value: Variant, field: String) -> Vector3: + if not value is Array or (value as Array).size() != 3: + _fail(asset_id, field + " must contain three numbers.") + return Vector3.ZERO + var values: Array = value + for number: Variant in values: + if not (number is float or number is int) or not is_finite(float(number)): + _fail(asset_id, field + " must contain finite numbers.") + return Vector3.ZERO + return Vector3(float(values[0]), float(values[1]), float(values[2])) + + +func _positive_size(size: Vector3) -> bool: + return size.is_finite() and size.x > 0.0 and size.y > 0.0 and size.z > 0.0 + + +func _near_vector(actual: Vector3, expected: Vector3) -> bool: + if not actual.is_finite() or not expected.is_finite(): + return false + var difference: Vector3 = (actual - expected).abs() + return maxf(difference.x, maxf(difference.y, difference.z)) <= TOLERANCE + + +func _fail(asset_id: String, message: String) -> void: + _errors.append("[%s] %s" % [asset_id, message]) + + +func _finish() -> void: + for message: String in _errors: + printerr("FAIL: " + message) + var label: String = "PASS" if _errors.is_empty() else "FAIL" + print("%s: Phase 4 models %d/%d; %d entries checked, %d errors." % [ + label, _passed, EXPECTED_ASSET_COUNT, _checked, _errors.size()]) + quit(0 if _errors.is_empty() else 1) diff --git a/tools/verify_phase4_models.gd.uid b/tools/verify_phase4_models.gd.uid new file mode 100644 index 0000000..c7e30ad --- /dev/null +++ b/tools/verify_phase4_models.gd.uid @@ -0,0 +1 @@ +uid://tpvxglosx2w2 diff --git a/tools/verify_phase4_standalone.py b/tools/verify_phase4_standalone.py new file mode 100644 index 0000000..7f37741 --- /dev/null +++ b/tools/verify_phase4_standalone.py @@ -0,0 +1,82 @@ +"""Blender integration audit of copied standalone scripts and scene preservation. + +Run in a separate process with --background --factory-startup --python-exit-code 1. +All generated test assets stay in a temporary directory, outside the project. +""" +from pathlib import Path +import json +import runpy +import shutil +import sys +import tempfile + +import bpy + +PROJECT = Path(__file__).resolve().parents[1] +CASES = [('melee', 'm04'), ('tank', 'g04'), ('ranged', 'w06'), + ('artillery', 'n08'), ('support', 'w10'), ('mercenary', 's04'), + ('worker', 'worker'), ('lane', 'map_lane_segment'), ('core', 'core_team1')] + + +def main(): + previous_scene = bpy.context.scene + cube = bpy.data.objects['Cube'] + cube.name = 'Body' + cube.location = (7, 8, 9) + material = bpy.data.materials.new('SW_glutpakt_primary_292B35') + material.diffuse_color = (.13, .27, .41, 1) + cube.data.materials.append(material) + old_color = tuple(material.diffuse_color) + old_slots = list(cube.data.materials) + old_objects = set(bpy.data.objects) + with tempfile.TemporaryDirectory(prefix='saumwacht-standalone-') as directory: + base = Path(directory) + scripts = base / 'scripts' + scripts.mkdir() + for source in (PROJECT / 'assets-source/phase4/standalone').glob('*.py'): + shutil.copy2(source, scripts / source.name) + + def run(role, asset_id, keep=False): + script = scripts / ('create_' + role + '.py') + sys.argv = [str(script), '--', '--id', asset_id, + '--export-dir', str(base / 'exports'), + '--blend-dir', str(base / 'blend')] + if not keep: + sys.argv.append('--no-keep-scene') + runpy.run_path(str(script), run_name='__main__') + + for role, asset_id in CASES: + run(role, asset_id) + assert bpy.context.scene == previous_scene, asset_id + assert set(bpy.data.objects) == old_objects, asset_id + assert tuple(cube.location) == (7, 8, 9), asset_id + assert tuple(material.diffuse_color) == old_color, asset_id + assert list(cube.data.materials) == old_slots, asset_id + assert (base / 'blend' / (asset_id + '.blend')).is_file(), asset_id + records = list(base.rglob(asset_id + '.json')) + assert len(records) == 1, (asset_id, records) + record = json.loads(records[0].read_text()) + assert record['resource_path'] is None, asset_id + assert Path(record['export_path']).is_file(), asset_id + print('STANDALONE_ISOLATION_PASS: 9/9; original scene, objects and material preserved') + + for _ in range(2): + run('melee', 'g01', keep=True) + assert len(bpy.data.scenes) == 3 + assert set(previous_scene.objects) == old_objects + assert tuple(material.diffuse_color) == old_color + assert len([o for o in bpy.data.objects if o.name.startswith('Model_g01')]) == 2 + print('KEEP_SCENE_PASS: two generated scenes and original scene retained') + + bpy.ops.wm.open_mainfile(filepath=str(base / 'blend/n08.blend')) + assert len(bpy.data.scenes) == 1 + objects = list(bpy.context.scene.objects) + assert all(o.type not in ('LIGHT', 'CAMERA') for o in objects) + assert any(o.name == 'Model_n08' for o in objects) + assert any(o.name == 'Forward' for o in objects) + assert not any(tuple(o.location) == (7, 8, 9) for o in objects) + print('NATIVE_BLEND_PASS: isolated N08 scene reopened;', len(objects), 'objects') + + +if __name__ == '__main__': + main() diff --git a/tools/verify_phase5.gd b/tools/verify_phase5.gd new file mode 100644 index 0000000..3a11bdb --- /dev/null +++ b/tools/verify_phase5.gd @@ -0,0 +1,211 @@ +extends Node +## Real eight-wave matches, runtime asset batching and visual acceptance captures. +## -- --capture renders the production scene; otherwise no display is required. + +const AI = preload("res://scripts/ai/simple_ai.gd") +const STEP: float = 1.0 / 60.0 +var checks: int = 0 +var failures: Array[String] = [] +var capture: bool = false +var main: Node3D +var battle: BattleController +var records: Array[Dictionary] = [] +var phase_id: String = "phase9-short" if "--phase9" in OS.get_cmdline_user_args() else "phase8-short" if "--phase8" in OS.get_cmdline_user_args() else "phase7" if "--phase7" in OS.get_cmdline_user_args() else ("phase6" if "--phase6" in OS.get_cmdline_user_args() else "phase5") + +func _ready() -> void: + WaveManager.set_physics_process(false) + capture = "--capture" in OS.get_cmdline_user_args() + call_deferred("_run") + +func _check(value: bool, message: String) -> void: + checks += 1 + if not value: + failures.append(message) + printerr("FAIL: ", message) + +func _run() -> void: + GameState.reset_match() + GameState.factions = ["glutpakt", "glutpakt"] + GameState.timed_build = true + GameState.select_mode(GameState.MODE_SHORT) + _check_assets() + if capture: + main = load("res://scenes/main.tscn").instantiate() + add_child(main) + battle = main.battle + await _capture("menu") + else: + battle = BattleController.new() + battle.render_enabled = false + add_child(battle) + WaveManager.attach_battle(battle) + await _play("Standard gegen Lernmodus", GameState.AI_STANDARD, GameState.AI_LEARNING, 0, true) + await _play("Standard gegen Standard", GameState.AI_STANDARD, GameState.AI_STANDARD, GameState.DRAW) + await _play("Leeres Baufeld gegen Standard", -1, GameState.AI_STANDARD, 1) + # Restart after a real loss restores controls, budget, workers and the first wave. + WaveManager.start_match() + _check(GameState.wave == 1 and GameState.phase == GameState.Phase.BUILD, "Restart begins wave one") + _check(GameState.core_hp == [3000,3000] and EconomyManager.get_team(0).gold == 220, "Restart restores normal starting state") + _check(EconomyManager.get_team(0).roster.is_empty() and EconomyManager.get_team(0).workers == 1, "Restart clears roster and workers") + _check(AssetLibrary.missing.is_empty(), "No required visual assets missing") + var output: String = "res://docs/" + phase_id + "-verification.json" + var file := FileAccess.open(output, FileAccess.WRITE) + file.store_string(JSON.stringify({"wave_count": DataCatalog.wave_count(), "checks":checks, + "failures":failures,"matches":records,"capture":capture}, "\t")) + file.close() + _write_balance_report() + print("PHASE5_PASS: %d checks; %d real-budget matches; %d failures" % [checks, records.size(), failures.size()]) + await Soundscape.quit_game(0 if failures.is_empty() else 1) + +func _check_assets() -> void: + var manifest: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("res://assets/phase4_manifest.json")) + var original_parts: int = 0 + var runtime_surfaces: int = 0 + for record: Dictionary in manifest.assets: + var visual: MeshInstance3D = AssetLibrary.instantiate_model(str(record.id)) as MeshInstance3D + _check(visual != null, "Runtime model exists: " + str(record.id)) + if visual == null: + continue + var triangles: int = 0 + for surface: int in range(visual.mesh.get_surface_count()): + var arrays: Array = visual.mesh.surface_get_arrays(surface) + var indices: PackedInt32Array = arrays[Mesh.ARRAY_INDEX] + var vertices: PackedVector3Array = arrays[Mesh.ARRAY_VERTEX] + triangles += (indices.size() if not indices.is_empty() else vertices.size()) / 3 + _check(triangles == int(record.triangles), "Batching preserves triangles: " + str(record.id)) + var expected_low := Vector3(record.bounds_godot.min[0],record.bounds_godot.min[1],record.bounds_godot.min[2]) + var expected_high := Vector3(record.bounds_godot.max[0],record.bounds_godot.max[1],record.bounds_godot.max[2]) + _check(visual.get_aabb().position.distance_to(expected_low) < .001 and visual.get_aabb().end.distance_to(expected_high) < .001, + "Batching preserves bounds: " + str(record.id)) + original_parts += int(record.mesh_parts) + runtime_surfaces += visual.mesh.get_surface_count() + visual.free() + print("RUNTIME_BATCHING: ", original_parts, " original parts -> ", runtime_surfaces, " material surfaces across catalog assets") + for id: String in DataCatalog.UNITS.keys() + DataCatalog.SENDS.keys() + ["worker","res_gold","res_sparks","res_income","res_core"]: + _check(AssetLibrary.icon(id) != null, "Icon exists: " + id) + for id: String in DataCatalog.UNITS: + var unit := CombatUnit.new() + add_child(unit) + unit.setup(DataCatalog.get_unit(id),1,0,false) + _check(unit.model_loaded, "Guardian uses actual model: " + id) + unit.play_attack(Vector3(1,0,1)) + unit.advance_status(.05) + unit.refresh_visuals() + var other := CombatUnit.new() + add_child(other) + other.setup(DataCatalog.get_unit(id),2,0,false) + _check(is_zero_approx(other.attack_flash), "Visual effects are per instance: " + id) + unit.free() + other.free() + for id: String in ["e01","e02","e03","e04","e07","e08"]: + var unit := CombatUnit.new() + add_child(unit) + unit.setup(DataCatalog.ENEMIES[id],2000000,0,true) + _check(unit.model_loaded, "Wave enemy has its own visual: " + id) + unit.free() + var fallback := CombatUnit.new() + add_child(fallback) + fallback.setup({"id":"unknown","ability":""},1,0,false) + fallback.refresh_visuals() + _check(not fallback.model_loaded and fallback.get_child_count() > 0, "Missing optional model has a working fallback") + fallback.free() + _check(DataCatalog.get_wave(9).is_empty() and DataCatalog.get_attackers(9).is_empty(), "No ninth wave") + _check(DataCatalog.WAVES[4].has("e07") and DataCatalog.WAVES[7].has("e08"), "Both boss waves are defined") + +func _play(title: String, player_level: int, rival_level: int, expected: int, screenshots: bool = false) -> void: + GameState.ai_level = rival_level + WaveManager.start_match() + var player := AI.new() + var waves: Array[Dictionary] = [] + var previous_roster: Dictionary = {} + for number: int in range(1, DataCatalog.wave_count() + 1): + _check(GameState.wave == number and GameState.phase == GameState.Phase.BUILD, title + ": build boundary") + if GameState.phase != GameState.Phase.BUILD: + break + if player_level >= 0: + player.plan(0,number,WaveManager.rival_snapshot(),GameState.last_reports[0],player_level) + var plan: Dictionary = EconomyManager.get_team(0) + var purchases: Array[String] = [] + for entry: Dictionary in plan.roster: + if previous_roster.get(entry.uid, "") != entry.type_id: + purchases.append(str(DataCatalog.get_unit(entry.type_id).display_name) + (" ↑" if previous_roster.has(entry.uid) else "")) + previous_roster[entry.uid] = entry.type_id + for team: int in range(2): + var own: Dictionary = EconomyManager.get_team(team) + _check(own.gold >= 0 and own.sparks >= 0, title + ": orders use real resources") + _check(EconomyManager.reserved_sparks(team) <= mini(own.sparks, EconomyManager.send_budget(number)), title + ": sends paid within budget") + if capture and screenshots and number in [1,5,8]: + main.viewed_team = 0 + main.hud.viewed_team = 0 + main._focus.x = -9.0 + main._place_camera() + main.selected_uid = int(EconomyManager.get_team(0).roster[0].uid) + main.hud.selected_uid = main.selected_uid + await _capture("build-%02d" % number) + var before_hp: Array = GameState.core_hp.duplicate() + WaveManager.ready_for_battle() + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: + break + WaveManager.advance(STEP) + if capture and screenshots and number in [5,8] and step == 330: + await _capture("boss-%02d" % number) + _check(GameState.phase in [GameState.Phase.RESULTS,GameState.Phase.GAME_OVER], title + ": battle terminates") + waves.append({"wave":number,"core_hp":GameState.core_hp.duplicate(), + "purchases":purchases,"workers_ordered":plan.pending_workers,"sends":plan.send_queue, + "damage":[before_hp[0]-GameState.core_hp[0],before_hp[1]-GameState.core_hp[1]], + "seconds":battle.elapsed,"leaks":battle.leaks.duplicate(), + "gold":[EconomyManager.get_team(0).gold,EconomyManager.get_team(1).gold], + "roster":[EconomyManager.get_team(0).roster.size(),EconomyManager.get_team(1).roster.size()]}) + if GameState.phase == GameState.Phase.GAME_OVER: + break + WaveManager.ready_for_battle() + _check(GameState.phase == GameState.Phase.GAME_OVER and GameState.outcome == expected, title + ": expected match result") + if player_level >= 0: + _check(GameState.wave == 8, title + ": survives all eight waves without injected resources") + if capture and screenshots: + await _capture("victory") + if capture and player_level < 0: + await _capture("defeat") + records.append({"title":title,"outcome":GameState.outcome,"waves":waves}) + print("SLICE_MATCH: ",title,"; wave ",GameState.wave,"; outcome ",GameState.outcome,"; cores ",GameState.core_hp) + +func _write_balance_report() -> void: + var lines: Array[String] = ["# Glutpakt · Daten und vollständige Testpartien", "", + "Aus den aktuellen Produktionsdaten und `tools/verify_phase5.gd` erzeugt. Alle Partien verwenden 220 Startgold, 3.000 Kern-HP und reguläre Käufe/Sends; feste Schritte von 1/60 s. KI gegen KI ist ein reproduzierbarer Funktionstest, keine Erfolgsquote für menschliche Spieler.", "", + "## Einheiten", "", "Jeder Grundangriff erfolgt einmal pro Sekunde. DPS hier ohne Brand, vierten Treffer, Flächenschaden oder Verstärkung. Bei Upgrades ist der angegebene Preis der Aufpreis zur Basiseinheit.", "", + "| ID | Einheit | Kauf / Aufpreis | HP | Grund-DPS | Reichweite | Schaden | Rüstung | Fähigkeit |", + "| --- | --- | ---: | ---: | ---: | ---: | --- | --- | --- |"] + for id: String in DataCatalog.UNITS: + var data: Dictionary = DataCatalog.get_unit(id) + lines.append("| %s | %s | %d | %d | %d | %.1f | %s | %s | %s |" % [id,data.display_name,data.cost,data.max_hp,data.damage,data.attack_range, + DataCatalog.DAMAGE_NAMES[data.attack_type],DataCatalog.ARMOR_NAMES[data.armor_type],data.ability_description]) + lines.append_array(["", "## Wellen", "", "| Welle | Titel | Gruppen | HP-Faktor | Schadensfaktor |", "| ---: | --- | --- | ---: | ---: |"]) + for number: int in range(1,DataCatalog.wave_count()+1): + var wave: Dictionary = DataCatalog.get_wave(number) + lines.append("| %d | %s | %s | %.3f | %.3f |" % [number,wave.title,wave.description,wave.hp_factor,wave.damage_factor]) + for record: Dictionary in records: + lines.append_array(["", "## " + str(record.title), "", "| Welle | Dauer s | Kern-HP 0 / 1 | Lecks 0 / 1 | Gold nach Kampf 0 / 1 | Wächter 0 / 1 |", "| ---: | ---: | ---: | ---: | ---: | ---: |"]) + for wave: Dictionary in record.waves: + lines.append("| %d | %.1f | %d / %d | %d / %d | %d / %d | %d / %d |" % [wave.wave,wave.seconds,wave.core_hp[0],wave.core_hp[1],wave.leaks[0],wave.leaks[1],wave.gold[0],wave.gold[1],wave.roster[0],wave.roster[1]]) + lines.append("\nErgebnis: " + ("Gleichstand" if record.outcome == -1 else "Front %d gewinnt" % record.outcome) + ".") + lines.append_array(["", "## Nachvollziehbarer Kaufplan gegen den Lernmodus", "", "Aufwertungen sind mit ↑ markiert. Die KI stellt Nahkämpfer vorn, Fernkämpfer zwei Reihen dahinter und Unterstützer dazwischen auf. Dies ist der tatsächlich bezahlte Plan der ersten Testpartie; andere Formationen und Eingaben können andere Ergebnisse liefern.", "", + "| Bauphase | Käufe / Aufwertungen | Arbeiter bestellt | Söldner-IDs |", "| ---: | --- | ---: | --- |"]) + for wave: Dictionary in records[0].waves: + lines.append("| %d | %s | %d | %s |" % [wave.wave,", ".join(wave.purchases),wave.workers_ordered,", ".join(wave.sends)]) + var file := FileAccess.open("res://docs/" + phase_id + "-balance.md",FileAccess.WRITE) + file.store_string("\n".join(lines) + "\n") + file.close() + +func _capture(label: String) -> void: + if not capture: + return + # Let the normal presentation catch up to the independently stepped simulation. + await get_tree().process_frame + await get_tree().create_timer(.3).timeout + await RenderingServer.frame_post_draw + var directory: String = "res://docs/screenshots/" + phase_id + DirAccess.make_dir_recursive_absolute(directory) + var error: Error = get_viewport().get_texture().get_image().save_png(directory + "/" + label + ".png") + _check(error == OK, "Screenshot saved: " + label) + print("PHASE5_CAPTURED: ",label) diff --git a/tools/verify_phase5.gd.uid b/tools/verify_phase5.gd.uid new file mode 100644 index 0000000..95d354b --- /dev/null +++ b/tools/verify_phase5.gd.uid @@ -0,0 +1 @@ +uid://de7g8kvm1ws1u diff --git a/tools/verify_phase5.tscn b/tools/verify_phase5.tscn new file mode 100644 index 0000000..88ddfc0 --- /dev/null +++ b/tools/verify_phase5.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tools/verify_phase5.gd" id="1"] + +[node name="Phase5Verification" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_phase6_runtime.gd b/tools/verify_phase6_runtime.gd new file mode 100644 index 0000000..e52efd2 --- /dev/null +++ b/tools/verify_phase6_runtime.gd @@ -0,0 +1,140 @@ +extends Node +const AI = preload("res://scripts/ai/simple_ai.gd") +var main: Node3D +var checks: int = 0 +var failures: Array[String] = [] +var expedition: bool = "--expedition" in OS.get_cmdline_user_args() + +func check(value: bool, message: String) -> void: + checks += 1 + if not value: + failures.append(message) + printerr("RUNTIME_FAIL: ", message) + +func key(code: Key) -> void: + var event := InputEventKey.new() + event.keycode = code + event.pressed = true + get_viewport().push_input(event,true) + event = event.duplicate() + event.pressed = false + get_viewport().push_input(event,true) + +func _ready() -> void: + call_deferred("run") + +func run() -> void: + GameState.reset_match() + GameState.factions = ["glutpakt", "glutpakt"] + GameState.timed_build = true + GameState.select_mode(GameState.MODE_SHORT) + main = load("res://scenes/main.tscn").instantiate() + add_child(main) + WaveManager.set_physics_process(false) + await get_tree().process_frame + main.hud._overlay_action.pressed.emit() + main.hud._starter_button.pressed.emit() + await get_tree().process_frame + var cursor := Vector2(530,360) + var press := InputEventMouseButton.new() + press.position = cursor + press.button_index = MOUSE_BUTTON_MIDDLE + press.pressed = true + get_viewport().push_input(press,true) + var motion := InputEventMouseMotion.new() + motion.position = cursor + Vector2(90,40) + motion.relative = Vector2(90,40) + motion.button_mask = MOUSE_BUTTON_MASK_MIDDLE + var initial_focus: Vector3 = main._focus + get_viewport().push_input(motion,true) + press = press.duplicate() + press.pressed = false + get_viewport().push_input(press,true) + check(main._manual_camera and main._focus != initial_focus, "Middle drag pans and disables auto-follow") + key(KEY_R) + check(not main._manual_camera and main._focus.is_equal_approx(initial_focus), "Reset resumes following") + main.hud._ready_button.grab_focus() + key(KEY_F1) + key(KEY_SPACE) + check(GameState.phase == GameState.Phase.BUILD and main.hud.settings_panel.visible, "Ready button cannot activate behind options") + key(KEY_ESCAPE) + check(main.hud._ready_button.has_focus(), "Closing options restores keyboard focus") + # Exercise volume, mute and lane filtering without altering saved preferences. + var old_mute: bool = Preferences.muted + var old_volume: float = Preferences.volume + Preferences.muted = false + Preferences.volume = .65 + Preferences.apply() + Soundscape.enabled = true + Soundscape.viewed_team = 0 + await get_tree().create_timer(.15).timeout + check(Soundscape.play("ability"), "An audible effect starts") + check(not Soundscape.play("ability"), "Immediate duplicate effect is rate-limited") + check(not Soundscape.play("stone",1,true), "Hidden lane is silent") + Preferences.muted = true + Preferences.apply() + check(not Soundscape.play("error"), "Mute prevents effects") + Preferences.muted = false + Preferences.apply() + # Advance seven regular waves, then render a timed 2x boss fight. + GameState.ai_level = GameState.AI_LEARNING + if expedition: + GameState.reset_match() + if "--wurzelbund" in OS.get_cmdline_user_args(): + GameState.factions = ["wurzelbund", "wurzelbund"] + GameState.select_mode(GameState.MODE_EXPEDITION) + GameState.ai_level = GameState.AI_STANDARD + WaveManager.start_match() + var ai := AI.new() + Soundscape.enabled = false + var last_wave: int = DataCatalog.wave_count() + main.battle.render_enabled = false + for number: int in range(1,last_wave+1): + ai.plan(0,number,WaveManager.rival_snapshot(),GameState.last_reports[0],GameState.AI_STANDARD) + if number == last_wave: + main.battle.render_enabled = true + WaveManager.ready_for_battle() + if number == last_wave: + break + for step: int in range(5401): + if GameState.phase != GameState.Phase.COMBAT: + break + WaveManager.advance(1.0/60.0) + WaveManager.ready_for_battle() + GameState.speed = 2 + Soundscape.enabled = true + WaveManager.set_physics_process(true) + await get_tree().create_timer(2.0).timeout + var frames: Array[float] = [] + var calls: Array[int] = [] + var start: int = Time.get_ticks_usec() + var previous: int = start + var sound_start: int = Soundscape.played + var units_start: int = main.battle.units.size() + while Time.get_ticks_usec() - start < 12000000: + await get_tree().process_frame + var now: int = Time.get_ticks_usec() + frames.append((now - previous)/1000.0) + calls.append(int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))) + previous = now + frames.sort() + calls.sort() + var mean: float = 0 + for value: float in frames: + mean += value + mean /= frames.size() + var sounds: int = Soundscape.played - sound_start + check(sounds > 0 and sounds <= 190, "2x audio stays bounded and produces effects") + var result: Dictionary = {"engine": Engine.get_version_info().string, "device": RenderingServer.get_video_adapter_name(), + "viewport": str(get_viewport().get_visible_rect().size), "wave": last_wave, "speed": 2, "sample_seconds": 12, + "units_at_start": units_start, "frames":frames.size(),"mean_frame_ms":mean,"p95_frame_ms":frames[floori(frames.size()*.95)], + "mean_fps":1000.0/mean,"max_draw_calls":calls.back(),"audio_events":sounds,"checks":checks,"failures":failures} + var phase: String = "phase10" if "--phase10" in OS.get_cmdline_user_args() else "phase9" if "--wurzelbund" in OS.get_cmdline_user_args() else "phase8" if expedition else ("phase7" if "--phase7" in OS.get_cmdline_user_args() else "phase6") + result["renderer"] = RenderingServer.get_current_rendering_method() + var file := FileAccess.open("res://docs/" + phase + "-runtime.json", FileAccess.WRITE) + file.store_string(JSON.stringify(result,"\t")); file.close() + print("PHASE6_RUNTIME: ",JSON.stringify(result)) + Preferences.volume = old_volume + Preferences.muted = old_mute + Preferences.apply() + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_phase6_runtime.gd.uid b/tools/verify_phase6_runtime.gd.uid new file mode 100644 index 0000000..8ea0b51 --- /dev/null +++ b/tools/verify_phase6_runtime.gd.uid @@ -0,0 +1 @@ +uid://cuh7w647nuhoi diff --git a/tools/verify_phase6_runtime.tscn b/tools/verify_phase6_runtime.tscn new file mode 100644 index 0000000..9471277 --- /dev/null +++ b/tools/verify_phase6_runtime.tscn @@ -0,0 +1,4 @@ +[gd_scene load_steps=2 format=3] +[ext_resource type="Script" path="res://tools/verify_phase6_runtime.gd" id="1"] +[node name="Phase6Runtime" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_quell.gd b/tools/verify_quell.gd new file mode 100644 index 0000000..06402b4 --- /dev/null +++ b/tools/verify_quell.gd @@ -0,0 +1,45 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ", label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("w10") + var b: Node3D = AssetLibrary.instantiate_fighter("w10") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count() == 17, "17 imported bones") + check(a.player != b.player and a.skeleton != b.skeleton, "independent skeleton and playback") + for clip: String in ["idle", "start", "walk", "stop", "attack_a", "attack_b", "hit", "ability", "death"]: + check(a.clips.has(clip), "imported clip " + clip) + check(a.clip_length(clip) > .3, "clip duration " + clip) + var arm: int = a.skeleton.find_bone("UpperArm.L") + var rest: Quaternion = b.skeleton.get_bone_pose_rotation(arm) + a.preview("walk", .40) + check(a.skeleton.find_bone("Thigh.L") >= 0, "has legs") + a.preview("attack_a", .90) + check(a.skeleton.get_bone_pose_rotation(arm).angle_to(rest) > .05, "left tendril attack moves arm") + a.preview("ability", .80) + check(a.current_clip == "ability" or a.clips.has("ability"), "multi-heal clip") + a.preview("idle", 0) + check(a.skeleton.get_bone_pose_rotation(arm).is_equal_approx(b.skeleton.get_bone_pose_rotation(arm)), "idle restores arms") + a.update_combat(1.0 / 60, 0, true, .6, 0, 0, 0, true) + check(a.current_clip == "attack_a", "combat left attack") + a.update_combat(1.0 / 60, 0, true, 0, 1, 0, 0, true) + check(absf(a.player.current_animation_position - .9) < .001, "contact frame") + a.update_combat(1.0 / 60, 0, true, .65, 1, 0, 0, true) + check(a.current_clip == "attack_b", "alternating right attack") + a.update_combat(1.0 / 60, 0, false, 0, 1, 0, 0, false) + check(a.dead and a.current_clip == "death", "death clip") + a.free() + b.free() + var f := FileAccess.open("res://docs/phase16-rig-verification.json", FileAccess.WRITE) + f.store_string(JSON.stringify({"checks": checks, "failures": failures}, "\t")) + f.close() + print("RIG_PASS: ", checks, " checks; ", failures.size(), " failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_quell.gd.uid b/tools/verify_quell.gd.uid new file mode 100644 index 0000000..9144f26 --- /dev/null +++ b/tools/verify_quell.gd.uid @@ -0,0 +1 @@ +uid://bg4tm4vj273vg diff --git a/tools/verify_quell.tscn b/tools/verify_quell.tscn new file mode 100644 index 0000000..60ac082 --- /dev/null +++ b/tools/verify_quell.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bq8quellverify"] + +[ext_resource type="Script" path="res://tools/verify_quell.gd" id="1"] + +[node name="VerifyQuell" type="Node"] +script = ExtResource("1") diff --git a/tools/verify_ringborke.gd b/tools/verify_ringborke.gd new file mode 100644 index 0000000..157c82c --- /dev/null +++ b/tools/verify_ringborke.gd @@ -0,0 +1,60 @@ +extends Node +var checks: int = 0 +var failures: Array[String] = [] +func check(ok: bool, label: String) -> void: + checks += 1 + if not ok: + failures.append(label) + printerr("RIG_FAIL: ",label) +func _ready() -> void: + call_deferred("run") +func run() -> void: + var a: Node3D = AssetLibrary.instantiate_fighter("w04") + var b: Node3D = AssetLibrary.instantiate_fighter("w04") + add_child(a) + add_child(b) + check(a.skeleton.get_bone_count()==27,"27 imported bones") + check(a.player!=b.player and a.skeleton!=b.skeleton,"independent skeleton and playback") + for clip: String in ["idle","start","walk","stop","attack_a","attack_b","hit","ability","death"]: + check(a.clips.has(clip),"imported clip "+clip) + check(a.clip_length(clip)>.3,"clip duration "+clip) + var left: int = a.skeleton.find_bone("Thigh.L") + var other: Quaternion = b.skeleton.get_bone_pose_rotation(left) + a.preview("walk",.35) + check(a.skeleton.get_bone_pose_rotation(left).angle_to(other)>.05,"walking deforms weighted leg") + check(b.skeleton.get_bone_pose_rotation(left).is_equal_approx(other),"second instance keeps pose") + a.preview("attack_a",.9) + var finger: int = a.skeleton.find_bone("Finger0.L") + a.preview("idle",0) + check(a.skeleton.get_bone_pose_rotation(finger).is_equal_approx(b.skeleton.get_bone_pose_rotation(finger)),"idle restores fingers after attack") + a.update_combat(1.0/60,0,true,.6,0,0,0,true) + check(a.current_clip=="attack_a" and absf(a.player.current_animation_position-.54)<.001,"first attack prepares before damage") + a.update_combat(1.0/60,0,true,0,1,0,0,true) + check(absf(a.player.current_animation_position-.9)<.001,"primary damage frame matches authored contact") + a.update_combat(1.0/60,0,true,.15,1,0,0,true) + check(a.player.current_animation_position>.9,"attack follow-through after damage") + a.update_combat(1.0/60,0,true,.65,1,0,0,true) + check(a.current_clip=="attack_b","alternating right attack") + var clock: float = a.player.current_animation_position + a.update_combat(0,0,true,.65,1,0,0,true) + check(is_equal_approx(a.player.current_animation_position,clock),"zero battle delta does not advance playback") + a.update_combat(1.0/60,0,true,.66,1,.5,.18,true) + check(a.current_clip=="attack_b","reactions preserve attack contact clock") + a.update_combat(1.0/60,0,false,0,1,0,0,false) + check(a.dead and a.current_clip=="death","death uses imported clip") + for i in range(180):a.update_combat(1.0/60,0,false,0,1,0,0,false) + check(absf(a.player.current_animation_position-a.clip_length("death"))<.001,"death holds final pose without looping") + var unit: Node3D = preload("res://scripts/combat/unit.gd").new() + add_child(unit) + unit.setup(DataCatalog.get_unit("w04"),1,0,false,Vector2i.ZERO,0,true) + unit.receive_damage(100000,0) + unit.refresh_visuals(.1) + check(not unit.alive and unit.visible and unit._model.dead,"dead unit remains visible for its death animation") + check(not unit._bars.visible and not unit._selection.visible,"dead health and selection are hidden") + unit.free() + a.free() + b.free() + var f := FileAccess.open("res://docs/phase11-rig-verification.json",FileAccess.WRITE) + f.store_string(JSON.stringify({"checks":checks,"failures":failures},"\t"));f.close() + print("RIG_PASS: ",checks," checks; ",failures.size()," failures") + await Soundscape.quit_game(0 if failures.is_empty() else 1) diff --git a/tools/verify_ringborke.gd.uid b/tools/verify_ringborke.gd.uid new file mode 100644 index 0000000..fc9777d --- /dev/null +++ b/tools/verify_ringborke.gd.uid @@ -0,0 +1 @@ +uid://dlyumqgr5fru3 diff --git a/tools/verify_ringborke.py b/tools/verify_ringborke.py new file mode 100644 index 0000000..c96daf3 --- /dev/null +++ b/tools/verify_ringborke.py @@ -0,0 +1,37 @@ +"""Validate the portable skin/animation asset, independent of Godot's wrapper.""" +from pathlib import Path +import json,math,sys +sys.path.insert(0,str(Path(__file__).resolve().parent)) +from verify_phase4_glb import GLB,topology +p=Path(__file__).resolve().parents[1];g=GLB(p/'assets/characters/ringborke.glb');d=g.doc +checks=[] +def check(v,msg): + assert v,msg + checks.append(msg) +check(len(d['skins'])==1,'one portable skin') +check(len(d['skins'][0]['joints'])==27,'27 distinct joint bindings') +expected={'idle','start','walk','stop','attack_a','attack_b','hit','ability','death'} +check({a['name'] for a in d['animations']}==expected,'nine complete clips') +weighted=0;total=0;max_error=0 +for m in d['meshes']: + for q in m['primitives']: + attr=q['attributes'] + vertices=g.accessor(attr['POSITION']);indices=[x[0] for x in g.accessor(q['indices'])] + t=topology(vertices,[indices[i:i+3] for i in range(0,len(indices),3)]) + check(t['closed'] and t['signed_volume']>0 and t['degenerate_triangles']==0,'closed outward geometry '+d['materials'][q['material']]['name']) + check(all(x in attr for x in ('JOINTS_0','WEIGHTS_0','POSITION','NORMAL','TEXCOORD_0')),'skin, normals and UVs') + joints=g.accessor(attr['JOINTS_0']);weights=g.accessor(attr['WEIGHTS_0']);normals=g.accessor(attr['NORMAL']) + for js,ws,n in zip(joints,weights,normals): + assert all(0<=j<27 for j in js) + assert all(math.isfinite(w) and 0<=w<=1 for w in ws) + max_error=max(max_error,abs(sum(ws)-1));weighted+=sum(w>.001 for w in ws)>1;total+=1 + assert all(math.isfinite(v) for v in n) +check(max_error<.0001,'all vertex weights normalized') +check(weighted/total>.15,'flexible tissue has blended joints') +for a in d['animations']: + check(len(a['channels'])>5,a['name']+' animates multiple joints') + for samp in a['samplers']: + times=[v[0] for v in g.accessor(samp['input'])];assert times==sorted(times) and times[0]>=0 + assert all(math.isfinite(x) for row in g.accessor(samp['output']) for x in row) +report={'checks':len(checks),'failures':[],'vertices':total,'blended_vertices':weighted,'blended_percent':round(weighted/total*100,2),'max_weight_sum_error':max_error,'clips':sorted(expected),'bones':27} +(p/'docs/phase11-skin-audit.json').write_text(json.dumps(report,indent=2)+'\n');print(report) diff --git a/tools/verify_ringborke.tscn b/tools/verify_ringborke.tscn new file mode 100644 index 0000000..b9c4b62 --- /dev/null +++ b/tools/verify_ringborke.tscn @@ -0,0 +1,4 @@ +[gd_scene load_steps=2 format=3] +[ext_resource type="Script" path="res://tools/verify_ringborke.gd" id="1"] +[node name="RingborkeVerification" type="Node"] +script = ExtResource("1")